← 返回首页
GitHub - gothing/draft: GODRAFT - self-documenting code · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus

gothing/draft

 master
Go to file
Code

Repository files navigation

More items

draft

Self-documenting code

Installing

go get github.com/gothing/draft

Communication & Articles

Usage

Setup API Endpoint

type UserEndpoint struct { draft.Endpoint } type UserEndpointParams struct { ID types.UserID `required:"true"` } type UserEndpointBody struct { ID types.UserID } func (ue *UserEndpoint) InitEndpointScheme(s *draft.Scheme) { s.URL("/api/v1/user") s.Description("...") s.Case(draft.Status.OK, "User object by ID", func () { id := types.GenUserID() // Request params s.Params(&UserEndpointParams{ ID: id, }) // Response body s.Body(&UserEndpointBody{ ID: id, }) }) }

Listen And Serve without implementation

But with mocks!

func main() { draftSrv := draft.Create(darft.Config{ DevMode: true, // Not production }) userAPI := draft.Compose( "User API", new(UserEndpoint), ) draftSrv.Add(userAPI) draftSrv.ListenAndServe(srv) }

Listen And Serve with custom ServeMux

Replace http.DefaultServeMux with custom one if you need.

func main() { mux := http.NewServeMux() draftSrv := draft.CreateWithMux(mux, darft.Config{ DevMode: true, // Not production }, ) userAPI := draft.Compose( "User API", new(UserEndpoint), ) draftSrv.Add(userAPI) draftSrv.ListenAndServe(srv) }

Listen And Serve with implementation

⚠️ See second argument for draftSrv.Add

func main() { draftSrv := draft.Create(darft.Config{ DevMode: true, // Not production }) userAPI := draft.Compose( "User API", new(UserEndpoint), ) draftSrv.Add(userAPI, MyDaemon{}) // <----- see here draftSrv.ListenAndServe(srv) } // MyDaemon - Example struct type MyDaemon struct {} // Routes - List of supported endpoints func (d MyDaemon) Routes() []string { return []string{"/api/v1/user"} // rest of endpoints will remain as mock } // ServeHTTP - classic HTTP handler func (d MyDaemon) ServeHTTP(w ResponseWriter, r *Request) { // ... }

Configuration

Настройка доки и прав доступа к endpoint (см. секцию Right).

func init() { draft.SetupDoc(draft.DocConfig{ // Публичный UI, который `godraft` выкачивает и вставлчяет него конфигурацию, // так что нет никакой опасности, что схемы-концов утекут «наружу», но если вы // фанат интима, то клонируйте https://github.com/gothing/draft-front и поднемайте // где вам спокойней FrontURL: "https://gothing.github.io/draft-front/", // Выбранная активная группа ActiveGroup: "demo", // Сами группы и их схемы, как видите там может быть массив из разных истоникой, // т.е. `godraft` можно просто поднять отдельно, а не в месте с вашим кодом (но я не советую) Groups: []draft.DocGroup{ // ID Название Источники описания «концов» {"demo", "Demo", []string{"http://localhost:2047/godraft:scheme/"}}, }, // Проекты и их найтсройки Projects: []draft.DocProject{ { ID: "auth", Name: "Auth", Host: "auth.mail.ru", HostRC: "test.auth.mail.ru", HostDEV: "localhost:2047", }, }, // Права доступа к endpiont Rights: []draft.DocAccess{ { // Идентификатор, который вы используете в коде при описание endpoint и его case ID: draft.Access.Auth, (на самом деле любая ваша константа, draft.Access.*это только пресет для удобства) // Название, которое отображается в интефейсе Name: "Auth", // Детализация прав доступа (какие хедеры и/или параметры нужно передать дополнительно) Extra: []draft.DocAccessExtra{ { Name: "mPOP", Cookies: struct { Cookie string `json:"cookie" required:"true" comment:"mPOP-куки"` }{"Mpop=...;"}, Params: struct { Token string `json:"token" required:"true" comment:"mPOP-токен"` }{"854724ce05861c2ce336e279039444a9%3A5441407e0..."}, }, { Name: "OAuth", Description: "Читать [тут](https://oauth.net/2/)", Params: struct { AccessToken string `json:"access_token" required:"true" comment:"OAuth-токен"` }{"36ee693610a344929218133291cd27ca..."}, }, }, }, }, }) }

Фабрика запросов

Первое что нужно понимать, она работает сразу из коробки, даже ничего настраивать не нужно, нажимаете кнопку в [>] в интерфейса, заполняете значения параметров запрос (по умолчанию они уже подставлены на основе выбранного case) и нажимаете Execute, изян 💁🏻‍♂️, запрос уходит в выбранный endpoint, а на выходе получается красивый JSON.

Но, всё становится интересней, когда доступ к «концу» ограничен «правами» (требуется авторизация или хитрая подписать на основе секретов от сервера), например:

Есть некий метод создания поста и доступен он только для авторизованного юзера:

s.Url("/api/v1/post/create") s.Access(draft.Access.Auth) // <--- вот это ограничение s.Case(draft.Status.OK, "Успех", func () { s.Params(CreateParams{ Title: "....", Content: "...", }) s.Body(CreateBody{ ID: types.GenID(), }) })

Фабрика и Права доступа

По умолчанию «Фабрика» ничего не знает о том как эти права интерпретировать, поэтому для начала в конфиге godraft нужно определить, как же работают у нас права:

Rights: []draft.DocAccess{ { ID: draft.Access.Auth, Name: "Auth", Extra: []draft.DocAccessExtra{ { Name: "OAuth2", Params: struct { AccessToken string `json:"access_token" required:"true" comment:"OAuth2-токен"` }{"36e..."}, ReqPrepare: prepareOAuth2Request, // <--- 🏭 }, }, }, },

Фабрика, по полученым данным найдет draft.Access.Auth -> OAuth2 и если у него определен метод ReqPrepare применит его к запросу:

func prepareOAuth2Request(req *http.Request) error { // модифицируем `req` добавляя в него `access_token` // (например тестового юзера) }

Вот и всё 🚀 (благодаря этой штуке я могу через итерфейс (!) дергать интернал методы и не знать беды, если вы понимаете о чем я говорю 😏)

About

GODRAFT - self-documenting code

Topics

Resources

Stars

6 stars

Watchers

3 watching

Forks

Packages

 
 
 

Contributors

Languages

Footer

© 2026 GitHub, Inc.