示例#1
0
文件: kami.go 项目: SLASH2NL/kami
// bless is the meat of kami.
// It wraps a ContextHandler into an httprouter compatible request,
// in order to run all the middleware and other special handlers.
func bless(k ContextHandler, base *context.Context, m *middlewares, panicHandler *HandlerType, logHandler *func(context.Context, mutil.WriterProxy, *http.Request), closeHandler *func(context.Context, *http.Request)) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
		ctx := defaultContext(*base, r)
		if len(params) > 0 {
			ctx = newContextWithParams(ctx, params)
		}
		ranLogHandler := false   // track this in case the log handler blows up
		ranCloseHandler := false // track this in case the log handler blows up

		writer := w
		var proxy mutil.WriterProxy
		if *logHandler != nil {
			proxy = mutil.WrapWriter(w)
			writer = proxy
		}

		if *panicHandler != nil {
			defer func() {
				if err := recover(); err != nil {
					ctx = newContextWithException(ctx, err)
					wrap(*panicHandler).ServeHTTPContext(ctx, writer, r)

					if *closeHandler != nil && !ranCloseHandler {
						(*closeHandler)(ctx, r)
					}

					if *logHandler != nil && !ranLogHandler {
						(*logHandler)(ctx, proxy, r)
						// should only happen if header hasn't been written
						proxy.WriteHeader(http.StatusInternalServerError)
					}

				}
			}()
		}

		ctx, ok := m.run(ctx, writer, r)
		if ok {
			k.ServeHTTPContext(ctx, writer, r)
		}

		if *closeHandler != nil {
			ranCloseHandler = true
			(*closeHandler)(ctx, r)
		}

		if *logHandler != nil {
			ranLogHandler = true
			(*logHandler)(ctx, proxy, r)
			// should only happen if header hasn't been written
			proxy.WriteHeader(http.StatusInternalServerError)
		}
	}
}
示例#2
0
文件: kami.go 项目: gunosy/kami
// bless is the meat of kami.
// It wraps a HandleFn into an httprouter compatible request,
// in order to run all the middleware and other special handlers.
func bless(k ContextHandler) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
		ctx := Context
		if len(params) > 0 {
			ctx = newContextWithParams(Context, params)
		}
		ranLogHandler := false // track this in case the log handler blows up

		writer := w
		var proxy mutil.WriterProxy
		if LogHandler != nil {
			proxy = mutil.WrapWriter(w)
			writer = proxy
		}

		if PanicHandler != nil {
			defer func() {
				if err := recover(); err != nil {
					ctx = newContextWithException(ctx, err)
					wrap(PanicHandler).ServeHTTPContext(ctx, writer, r)

					if LogHandler != nil && !ranLogHandler {
						LogHandler(ctx, proxy, r)
						// should only happen if header hasn't been written
						proxy.WriteHeader(500)
					}
				}
			}()
		}

		ctx, ok := run(ctx, writer, r)
		if ok {
			k.ServeHTTPContext(ctx, writer, r)
		}

		if LogHandler != nil {
			ranLogHandler = true
			LogHandler(ctx, proxy, r)
			// should only happen if header hasn't been written
			proxy.WriteHeader(500)
		}
	}
}