import "github.com/guregu/kami" ou import "gopkg.in/guregu/kami.v2"
Kami (神) é uma pequena estrutura da web usando o contexto de contexto de solicitação e httptreemux para roteamento. Ele inclui um sistema simples para executar o middleware hierárquico antes e depois das solicitações, além de ganchos de log e pânico. O reinício gracioso via Einhorn também é apoiado.
Kami foi projetado para ser usado como ponto de registro central para suas rotas, middleware e contexto "objeto de Deus". Você é incentivado a usar as funções globais, mas a Kami suporta vários muxes com kami.New() .
Você é livre para montar kami.Handler() onde quiser, mas é fornecida uma função kami.Serve() é fornecida.
Aqui está uma apresentação sobre o nascimento de Kami, explicando algumas das opções de design.
Tanto context quanto x/net/context são suportados.
Um exemplo artificial usando kami e contexto para localizar saudações.
Pule ⏩
// Nosso WebServerpackage mainimport ("fmt" "net/http" "context" "github.com/guregu/kami" "github.com/my-github/greeting" // consulte a saudação do pacote abaixo) Func Greet (contexto do CTX. Contexto, w http.Responsewriter, r *http.request) {hello: = saudação.FromContext (ctx) Nome: = kami.param (ctx, "name") fmt.fprintf (w, " %s, %s!", Olá, nome)
} func main () {ctx: = context.background () ctx = saudação.withcontext (ctx, "hello") // Definir padrão Greetingkami.Context = ctx // Defina nosso "contexto de Deus", o contexto base para todos os pedidos .Use ("/hello/", saudação.guess) // use este middleware para caminhos em /hello/kami.get("/hello/:name ", greet) // Adicione um manipulador de get com um parâmetro no urlkami.serve () // serve graciosamente com suporte para Einhorn e Systemd} // Pacotes Greeting Lojas Setores de saudação em contexto.Package Greetingimport ("net/http" "context" "Golang.org/x/text/language") // Para obter mais informações sobre o contexto e por que estamos fazendo isso, // Consulte https://blog.golang.org/ContextType ctxKey Intvar Key ctxKey = 0VAR cumprimentos = map [idioma.tag] string {linguy.americanenglish: "yo", idioma.japanese: "こんにちは",
} // acho que o middleware Kami é que examina a Language aceita e define // a saudação para uma melhor, se possível. , _, err: = idioma.parseAcceptLanguage (r.header.get ("aceitar linguagem")); err == nil {para _, t: = tag range {se g, ok: = saudações [t]; ok {ctx = withcontext (ctx, g) retorna ctx
}
}
} return ctx} // withcontext retorna um novo contexto com a saudação dada.func withcontext (ctx context.Context, saudação string) context.Context {return context.withValue (ctx, chave, saudação)
} // FromContext Recupera a saudação deste contexto, // ou retorna uma sequência vazia se desaparecida.func fromcontext (ctx context.context) string {hello, _: = ctx.value (key). (String) retornar hello} Configurar rotas usando kami.Get("/path", handler) , kami.Post(...) , etc. Você pode usar parâmetros nomeados ou curingas em URLs como /hello/:name/edit ou /files/*path e acessá -los usando o contexto que Kami fornece: kami.Param(ctx, "name") . Veja as regras de roteamento e a prioridade de roteamento. Os seguintes tipos de manipuladores são aceitos:
Tipos que implementam kami.ContextHandler
func(context.Context, http.ResponseWriter, *http.Request)
Tipos que implementam http.Handler
func(http.ResponseWriter, *http.Request)
Todos os contextos que Kami usa são descendentes de kami.Context : Este é o "objeto de Deus" e o homônimo deste projeto. Por padrão, este é context.Background() , mas sinta-se à vontade para substituí-lo por um contexto pré-inicializado adequado ao seu aplicativo.
Construa a segmentação do Google App Engine envolverá automaticamente o contexto "God Object" com o contexto por solicitação do mecanismo do App.
Adicione o middleware com kami.Use("/path", kami.Middleware) . O middleware é executado antes dos pedidos e pode detê -los mais cedo. Mais no middleware abaixo.
Adicione pós -ware com kami.After("/path", kami.Afterware) . Pós -ware é executado após solicitações.
Defina kami.Cancel como true para cancelar automaticamente todos os contextos de todos os pedidos após o término da solicitação. Ao contrário da biblioteca padrão, Kami não cancelou contextos por padrão.
Você pode fornecer um manipulador de pânico definindo kami.PanicHandler . Quando o manipulador de pânico é chamado, você pode acessar o erro de pânico com kami.Exception(ctx) .
Você também pode fornecer um kami.LogHandler que envolverá todas as solicitações. kami.LogHandler tem uma assinatura de função diferente, levando um WriterProxy que tem acesso ao código de status da resposta, etc.
Use kami.Serve() para servir graciosamente sua aplicação ou monte kami.Handler() em algum lugar conveniente.
Middleware Func (Context.Context, http.Responsewriter, *http.request) Context.Context
O middleware difere de um HandlerType, pois retorna um novo contexto. Você pode aproveitar isso para construir seu contexto registrando o middleware nos caminhos de aprovação. Como um caso especial, você pode devolver o NIL para interromper a execução da cadeia de middleware.
O middleware é hierárquico. Por exemplo, uma solicitação de /hello/greg executará o middleware registrado nos seguintes caminhos, em ordem:
/
/hello/
/hello/greg
Dentro de um caminho, o middleware é executado na ordem do registro.
func init () {kami.use ("/", login) kami.use ("/private/", loginRequired)
} // O login retorna um novo contexto com o objeto de usuário apropado Inside Func Login (ctx context.Context, w http.ResponseWriter, r *http.request) context.Context {se u, err: = user.getByToken (ctx, r. Formalue ("auth_token")); err == nil {ctx = user.newcontext (ctx, u)
} retornar ctx} // LoginRewired interrompe a solicitação se não tivermos um objeto de usuário LoginRequired (ctx context.Context, w http.Responsewriter, r *http.request) context.Context {if _, ok: = user.FromContext (ctx); ! ok {W.WriteHeader (http.statusforbidden) // ... render 503 proibido PageReturn nil
} Retorne ctx}Os parâmetros nomeados e os curingas no middleware são suportados agora. O middleware registrado sob um caminho com um curinga será executado após todo o middleware hierárquico.
kami.use ("/user/: id/edit", checkAdminPermissions) // corresponde apenas ao , se comporta como caminhos não parameterizados Kami também pode usar o middleware HTTP de baunilha. kami.Use aceita funções na forma de func(next http.Handler) http.Handler . Esteja aconselhado que Kami executará esse middleware em sequência, não em uma cadeia. Isso significa que madeireiros e manipuladores de pânico padrão não funcionam como você espera. Você deve usar kami.LogHandler e kami.PanicHandler .
O exemplo a seguir usa o Goji/httpauth para adicionar autenticação básica HTTP aos caminhos em /secret/ .
importação ("github.com/goji/httpauth""github.com/guregu/kami")func main () {kami.use ("/secret/", httpauth.simplebasicauth (" nome de usuário "," senha ")) Kami) .Get ("/secret/message", secretMessageHandler) kami.serve ()
}Digite Func AfterWare (Context.Context, Mutil.WriterProxy, *http.request) Context.Context
func init () {kami.after ("/", limpeza)
}Executando após o manipulador de solicitação, o pós -ware é útil para limpar. Afterware é como uma imagem espelhada do middleware. Afterware também é executado hierarquicamente, mas na ordem inversa do middleware. Os curingas são avaliados antes do pós -louça hierárquica.
Por exemplo, uma solicitação de /hello/greg executará pós -ware registrado nos seguintes caminhos:
/hello/greg
/hello/
/
Isso dá à Afterware sob caminhos específicos a capacidade de usar recursos que podem ser fechados por / .
Ao contrário do middleware, o pós -louça que retorna nil não impedirá que o restante pós -ware seja avaliado.
kami.After("/path", afterware) suporta muitos tipos diferentes de funções, consulte os documentos para kami.AfterwareType para obter mais detalhes.
*kami.Mux Kami foi originalmente projetado para ser a "cola" entre vários pacotes em um aplicativo da Web complexo. As funções globais e kami.Context são uma maneira fácil de seus pacotes trabalharem juntos. No entanto, se você deseja usar o KAMI como um servidor incorporado em outro aplicativo, sirva duas pilhas Kami separadas em portas diferentes ou, de outra forma, gostaria de ter uma versão não global do kami, kami.New() pode ser útil.
Chamar kami.New() retorna um novo *kami.Mux , uma pilha Kami completamente independente. Alterações no kami.Context , os caminhos registrados com kami.Get() et al, e o middleware global registrado com kami.Use() não afetará um *kami.Mux .
Em vez disso, com mux := kami.New() você pode alterar mux.Context , ligue para mux.Use() , mux.Get() , mux.NotFound() , etc.
*kami.Mux implementa http.Handler , para que você possa usá -lo como quiser!
// Pacote Admin é um pluginpackage do servidor do painel de administração Adminimport ("net/http" "github.com/guregu/kami") // Monte automaticamente nosso admin stufffunc () {mux: = kami.new () Mux. Context = AdmiNContextMux.use ("/", Authorize) mux.get ("/admin/Memstats", MemoryStats) mux.post ("/admin/die", desligamento) // ... http.handle ("/admin/", mux)
}Mit
httptreemux: roteador
Goji: Graceful, WriterProxy