import "github.com/guregu/kami"
o import "gopkg.in/guregu/kami.v2"
Kami (神) es un pequeño marco web que utiliza el contexto para el contexto de solicitud y httptreemux para el enrutamiento. Incluye un sistema simple para ejecutar el middleware jerárquico antes y después de las solicitudes, además de los ganchos de registro y pánico. El reinicio gracioso a través de Einhorn también es compatible.
Kami está diseñado para ser utilizado como punto de registro central para sus rutas, middleware y contexto "objeto de Dios". Se le recomienda usar las funciones globales, pero Kami admite múltiples muxes con kami.New()
.
Usted es libre de montar kami.Handler()
donde quiera, pero se proporciona una función útil kami.Serve()
.
Aquí hay una presentación sobre el nacimiento de Kami, explicando algunas de las opciones de diseño.
Tanto context
como x/net/context
son compatibles.
Un ejemplo artificial usando Kami y contexto para localizar los saludos.
Sk ⏩
// Nuestro WebServerPackage MainImport ("fmt" "net/http" "context" "github.com/guregu/kami" "github.com/my-github/greeting" // consulte el saludo de paquete a continuación) FUNC Greet (contexto CTX. Contexto, w http.ResponseWriter, r *http.request) {Hello: = saludo.fromContext (CTX) Nombre: = kami.param (ctx, "nombre") fmt.fprintf (w, " %s, %s!", hola, nombre) } func Main () {ctx: = context.background () ctx = greeting.withContext (ctx, "hello") // establece un saludo predeterminadokami.context = ctx // establece nuestro "contexto de Dios", el contexto base para todos los requestskami .Use ("/hello/", greeting.guess) // usa este middleware para rutas debajo /hello/kami.get("/hello/:name ", greet) // Agregar un controlador Get con un parámetro en urlkami.serve () // Sirve con gracia con soporte para Einhorn y Systemd}
// Configuración de saludo de las tiendas de saludo en el contexto. Package GreetingImport ("net/http" "context" "golang.org/x/text/language") // para obtener más información sobre el contexto y por qué estamos haciendo esto, // Consulte https://blog.golang.org/contexttype ctxkey intvar key ctxkey = 0var greetings = MAP [Language.tag] String {Language.AmericanEnglish: "Yo", Language.Japanese: "こんにちは", } // Supongo que es kami middleware que examina el idioma aceptable y los conjuntos // el saludo a uno mejor si es posible. , _, err: = language.ParseAcceptLanguage (R.Header.get ("Accept-Language")); err == nil {para _, t: = rango etiqueta {if g, ok: = saludos [t]; OK {ctx = withContext (ctx, g) return ctx } } } return ctx} // withcontext devuelve un nuevo contexto con el saludo dado.func withcontext (ctx context.context, saludo string) context.context {return context.withvalue (ctx, key, saludo) } // fromcontext recupera el saludo de este contexto, // o devuelve una cadena vacía si falta.func fromcontext (ctx context.context) cadena {hola, _: = ctx.value (key). (String) return hello}
Configurar rutas usando kami.Get("/path", handler)
, kami.Post(...)
, etc. Puede usar parámetros o comodines en URL como /hello/:name/edit
o /files/*path
y acceder a ellos usando el contexto que Kami te da: kami.Param(ctx, "name")
. Consulte las reglas de enrutamiento y la prioridad de enrutamiento. Se aceptan los siguientes tipos de manejadores:
tipos que implementan kami.ContextHandler
func(context.Context, http.ResponseWriter, *http.Request)
tipos que implementan http.Handler
func(http.ResponseWriter, *http.Request)
Todos los contextos que Kami usa desciende de kami.Context
: este es el "objeto de Dios" y el homónimo de este proyecto. Por defecto, esto es context.Background()
, pero no dude en reemplazarlo con un contexto preinicializado adecuado para su aplicación.
Las compilaciones dirigidas a Google App Engine envolverán automáticamente el contexto del "objeto dios" con el contexto por solicitud del motor de la aplicación.
Agregue el middleware con kami.Use("/path", kami.Middleware)
. El middleware se ejecuta antes de las solicitudes y puede detenerlos temprano. Más sobre el middleware a continuación.
Agregue Afterware con kami.After("/path", kami.Afterware)
. Afterware se ejecuta después de las solicitudes.
Establezca kami.Cancel
en true
para cancelar automáticamente todos los contextos de la solicitud después de que se termine la solicitud. A diferencia de la biblioteca estándar, Kami no cancela contextos de forma predeterminada.
Puede proporcionar un controlador de pánico configurando kami.PanicHandler
. Cuando se llama al controlador de pánico, puede acceder al error de pánico con kami.Exception(ctx)
.
También puede proporcionar un kami.LogHandler
que envuelva todas las solicitudes. kami.LogHandler
tiene una firma de función diferente, llevando a un escritor que tiene acceso al código de estado de respuesta, etc.
Use kami.Serve()
para servir con gracia su aplicación, o monte kami.Handler()
en algún lugar conveniente.
Tipo de middleware func (context.context, http.ResponseWriter, *http.request) context.context
El middleware difiere de un Handlertype en que devuelve un nuevo contexto. Puede aprovechar esto para construir su contexto registrando el middleware en las rutas de aprendizaje. Como caso especial, puede devolver nulo para detener la ejecución de la cadena de middleware.
El middleware es jerárquico. Por ejemplo, una solicitud para /hello/greg
ejecutará Middleware registrada en las siguientes rutas, en orden:
/
/hello/
/hello/greg
Dentro de una ruta, el middleware se ejecuta en el orden de registro.
Func init () {kami.use ("/", login) kami.use ("/private/", loginRquired) } // El inicio de sesión Devuelve un nuevo contexto con el objeto de usuario Apropiate dentro de la sesión de sesión (ctx context.context, w http.ResponseWriter, r *http.request) context.context {if u, err: = user.getByToken (ctx, r. Formvalue ("auth_token")); err == nil {ctx = user.newContext (ctx, u) } return ctx} // loginRequired detiene la solicitud si no tenemos un usuario ObjectFuncfunc loginRequired (ctx context.context, w http.Responsewriter, r *http.request) context.context {If _, ok: = user.fromContext (CTX); ! Ok {w.writeHeader (http.statusForbidden) // ... Render 503 Pagereturn prohibido Nil } return ctx}
Los parámetros con nombre y comodines en el middleware son compatibles ahora. El middleware registrado en una ruta con un comodín se ejecutará después de todo el middleware jerárquico.
kami.use ("/user/: id/edit", checkadminpermissions) // solo coincide /user/:id/editkami.use("/user/:id/edit/* ", checkadMinpermissions) // coincide con todas las rutas de inherencia , se comporta como caminos no parameterizados
Kami también puede usar el middleware HTTP de vainilla. kami.Use
acepta funciones en forma de func(next http.Handler) http.Handler
. Tenga en cuenta que Kami ejecutará dicho middleware en secuencia, no en una cadena. Esto significa que los registradores estándar y los manejadores de pánico no funcionarán como espere. Debes usar kami.LogHandler
y kami.PanicHandler
en su lugar.
El siguiente ejemplo usa goji/httpauth para agregar http autenticación básica a las rutas debajo /secret/
.
import ("github.com/goji/httpauth""github.com/gurgu/kami")func main () {kami.use ("/secret/", httpauth.simplebasicauth (" nombre de usuario "," contraseña ")) Kami .Get ("/secret/mensaje", secretMessageHandler) kami.serve () }
escriba FUNC (context.context, Mutil.WriterProxy, *http.request) context.context.context.context
Func init () {kami.after ("/", limpieza) }
Ejecutando después del controlador de solicitud, Afterware es útil para limpiar. Afterware es como una imagen de espejo del middleware. Afterware también se ejecuta jerárquicamente, pero en el orden inverso del middleware. Los comodines se evalúan antes de los jerárquicos posteriores.
Por ejemplo, una solicitud para /hello/greg
se ejecutará Afterware registrada en las siguientes rutas:
/hello/greg
/hello/
/
Esto le da a Afterware en rutas específicas la capacidad de usar recursos que pueden cerrarse por /
.
A diferencia del middleware, el retorno de Afterware NIL no evitará que se evalúe el restante después de ser evaluado.
kami.After("/path", afterware)
admite muchos tipos diferentes de funciones, consulte los documentos de kami.AfterwareType
para obtener más detalles.
*kami.Mux
Kami fue diseñado originalmente para ser el "pegamento" entre múltiples paquetes en una aplicación web compleja. Las funciones globales y kami.Context
son una manera fácil para que sus paquetes funcionen juntos. Sin embargo, si desea usar Kami como servidor integrado dentro de otra aplicación, sirva dos pilas de Kami separadas en diferentes puertos, o de lo contrario le gustaría tener una versión no global de Kami, kami.New()
puede ser útil.
Llamar kami.New()
devuelve un nuevo *kami.Mux
, una pila Kami completamente independiente. Los cambios en kami.Context
, las rutas registradas con kami.Get()
et al, y el middleware global registrado con kami.Use()
no afectará a *kami.Mux
.
En su lugar, con mux := kami.New()
puede cambiar mux.Context
, llamar mux.Use()
, mux.Get()
, mux.NotFound()
, etc.
*kami.Mux
implementa http.Handler
, por lo que puede usarlo como desee.
// paquete admin es un servidor web de administrador pluginpackage adminimport ("net/http" "github.com/guregu/kami") // Monta automáticamente nuestro stuff de administrador secreto init () {mux: = kami.new () Mux. Context = admincontextmux.use ("/", autorizar) mux.get ("/admin/memstats", MemoryStats) mux.post ("/admin/die", apagado) // ... http.handle ("/admin/", mux) }
MIT
httptreemux: enrutador
Goji: Greyful, WriterProxy