func (self Blog) ServeHTTP(w http.ResponseWriter, r *http.Request) { tpl, err := template.ParseFiles(self.TplPath) if err != nil { log.Fatal(err) } // data is the template data for the Blog. data := struct { // Posts is the slice of posts for this blog page. Posts []post }{} // Pull out {…} variables from muxer. vars := mux.Vars(r) switch mux.CurrentRoute(r).GetName() { case "post": data.Posts = make([]post, 1) newPost, err := self.getPost(vars["year"], vars["month"], vars["day"], vars["name"]) if err != nil { log.Fatal(err) } data.Posts[0] = *newPost default: data.Posts, err = self.getPage(0) } tpl.Execute(w, data) }
func getPasteRawHandler(o Model, w http.ResponseWriter, r *http.Request) { p := o.(*Paste) mime := "text/plain" ext := "txt" if mux.CurrentRoute(r).GetName() == "download" { lang := p.Language if lang != nil { if len(lang.MIMETypes) > 0 { mime = lang.MIMETypes[0] } if len(lang.Extensions) > 0 { ext = lang.Extensions[0] } } filename := p.ID.String() if p.Title != "" { filename = p.Title } w.Header().Set("Content-Disposition", "attachment; filename=\""+filename+"."+ext+"\"") w.Header().Set("Content-Transfer-Encoding", "binary") } w.Header().Set("Content-Security-Policy", "default-src 'none'") w.Header().Set("Content-Type", mime+"; charset=utf-8") reader, _ := p.Reader() defer reader.Close() io.Copy(w, reader) }
func (sc *ServerConfig) metadata(w http.ResponseWriter, req *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") vars := mux.Vars(req) clientIp := sc.requestIp(req) version := vars["version"] wait := mux.CurrentRoute(req).GetName() == "Wait" oldValue := vars["oldValue"] maxWait, _ := strconv.Atoi(req.URL.Query().Get("maxWait")) answers := sc.answers() _, ok := answers[version] if !ok { // If a `latest` key is not provided, pick the ASCII-betically highest version and call it that. if version == "latest" { version = "" for _, k := range answers.Versions() { if k > version { version = k } } logrus.Debugf("Picked %s for latest version because none provided", version) } else { respondError(w, req, "Invalid version", http.StatusNotFound) return } } path := strings.TrimRight(req.URL.EscapedPath()[1:], "/") pathSegments := strings.Split(path, "/")[1:] displayKey := "" var err error for i := 0; err == nil && i < len(pathSegments); i++ { displayKey += "/" + pathSegments[i] pathSegments[i], err = url.QueryUnescape(pathSegments[i]) } if err != nil { respondError(w, req, err.Error(), http.StatusBadRequest) return } logrus.WithFields(logrus.Fields{ "version": version, "client": clientIp, "wait": wait, "oldValue": oldValue, "maxWait": maxWait}).Debugf("Searching for: %s", displayKey) val, ok := sc.lookupAnswer(wait, oldValue, version, clientIp, pathSegments, time.Duration(maxWait)*time.Second) if ok { logrus.WithFields(logrus.Fields{"version": version, "client": clientIp}).Debugf("OK: %s", displayKey) respondSuccess(w, req, val) } else { logrus.WithFields(logrus.Fields{"version": version, "client": clientIp}).Infof("Error: %s", displayKey) respondError(w, req, "Not found", http.StatusNotFound) } }
func BeforeAPICall(app string, r *http.Request) { c := &Call{ App: app, Host: hostname, RemoteAddr: r.RemoteAddr, UserAgent: r.UserAgent(), URL: r.URL.String(), HTTPMethod: r.Method, Route: mux.CurrentRoute(r).GetName(), RouteParams: mapStringStringAsParams(mux.Vars(r)), QueryParams: mapStringSliceOfStringAsParams(r.URL.Query()), Start: time.Now().In(time.UTC), } if parentCallID, ok := GetParentCallID(r); ok { c.ParentCallID = nnz.Int64(parentCallID) } if CurrentUser != nil { c.UID = nnz.Int(CurrentUser(r)) } err := insertCall(c) if err != nil { log.Printf("insertCall failed: %s", err) } setCallID(r, c.ID) }
func (nd *NegroniDog) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { start := time.Now() next(rw, r) statPrefix := "http" if mux.CurrentRoute(r) != nil && mux.CurrentRoute(r).GetName() != "" { statPrefix += "." + mux.CurrentRoute(r).GetName() } //resp time responseTime := time.Since(start) statName := strings.Join([]string{statPrefix, "resp_time"}, ".") nd.Cli.Histogram(statName, responseTime.Seconds(), nil, 1) //resp code statName = strings.Join([]string{statPrefix, "status_code", strconv.Itoa(rw.(negroni.ResponseWriter).Status())}, ".") nd.Cli.Count(statName, 1, nil, 1) }
// TrackAPICall wraps an API endpoint handler and records incoming API calls. func TrackAPICall(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { c := &Call{ URL: r.URL.String(), Route: mux.CurrentRoute(r).GetName(), RouteParams: mapStringStringAsParams(mux.Vars(r)), QueryParams: mapStringSliceOfStringAsParams(r.URL.Query()), Date: time.Now(), } // Try to get the current view info from the X-Track-View header. viewID, err := GetViewID(r) if err != nil { log.Printf("GetViewID failed: %s", err) w.WriteHeader(http.StatusInternalServerError) return } if viewID != nil { c.Instance = viewID.Instance c.ViewSeq = nnz.Int(viewID.Seq) } // Otherwise, try to get the instance from the request context. if c.Instance == 0 { if i := GetInstance(r); i != 0 { c.Instance = i } } err = InsertCall(c) if err != nil { log.Printf("InsertCall failed: %s", err) w.WriteHeader(http.StatusInternalServerError) return } status := CallStatus{ CallID: c.ID, Panicked: true, // assume the worst, set false if no panic } start := time.Now() rw := newRecorder(w) defer func() { status.Duration = time.Since(start).Nanoseconds() status.BodyLength = rw.BodyLength status.HTTPStatusCode = rw.Code err := InsertCallStatus(&status) if err != nil { log.Printf("warn: UpdateCallStatus failed (ID=%d): %s", c.ID, err) } }() h.ServeHTTP(rw, r) status.Panicked = false }) }
func logError(req *http.Request, err error, rv interface{}) { if err != nil { var buf bytes.Buffer fmt.Fprintf(&buf, "Error serving %s (route %s): %s\n", req.URL, mux.CurrentRoute(req).GetName(), err) if rv != nil { fmt.Fprintln(&buf, rv) buf.Write(debug.Stack()) } log.Print(buf.String()) } }
/* This is the handler where all the requests to providers will land in. Here the parameters are extracted and passed to the providers along with the requestbody if any using RPC. Result will be parsed to see if a specific status code needs to be set for http response. Arguments to Provider function - 1. type RpcRequest struct { RpcRequestVars map[string]string RpcRequestData []byte } Each provider should expect this structure as the first argument. RpcRequestVars is a map of parameters passed in request URL. RpcRequestData is the payload(body) of the http request. 2.Result - *[]byte Pointer to a byte array. In response, the byte array should contain { "status": {"statuscode": <Code>, "statusmessage": "<msg>"}, "data": {"requestid": "<id>", "result": []byte} } where result is response payload from the provider, RequestId is populated if the request is asynchronously executed and statuscode and statusmessage to be set in the status field. The statuscode field should be valid http status code */ func (a *App) ProviderHandler(w http.ResponseWriter, r *http.Request) { ctxt, err := GetContext(r) if err != nil { logger.Get().Error("Error Getting the context. error: %v", err) } //Parse the Request and get the parameters and route information route := mux.CurrentRoute(r) vars := mux.Vars(r) var result []byte //Get the route details from the map routeCfg := a.routes[route.GetName()] //Get the request details from requestbody body, err := ioutil.ReadAll(r.Body) if err != nil { logger.Get().Error("%s-Error parsing http request body: %v", ctxt, err) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Error parsing the http request body")) } //Find out the provider to process this request and send the request //After getting the response, pass it on to the client provider := a.getProviderFromRoute(ctxt, routeCfg) if provider != nil { logger.Get().Info("%s-Sending the request to provider: %s", ctxt, provider.Name) provider.Client.Call(provider.Name+"."+routeCfg.PluginFunc, models.RpcRequest{RpcRequestVars: vars, RpcRequestData: body}, &result) //Parse the result to see if a different status needs to set //By default it sets http.StatusOK(200) logger.Get().Info("Got response from provider: %s", provider.Name) var m models.RpcResponse if err = json.Unmarshal(result, &m); err != nil { logger.Get().Error("%s-Unable to Unmarshall the result from provider: %s. error: %v", ctxt, provider.Name, err) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Unable to unmarshall the result from provider")) } status := m.Status.StatusCode if status != http.StatusOK { w.WriteHeader(int(status)) } w.Write(result) return } else { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Matching Provider Not Found")) } }
// Add the access record for the catalog if it's our current route func appendCatalogAccessRecord(accessRecords []auth.Access, r *http.Request) []auth.Access { route := mux.CurrentRoute(r) routeName := route.GetName() if routeName == v2.RouteNameCatalog { resource := auth.Resource{ Type: "registry", Name: "catalog", } accessRecords = append(accessRecords, auth.Access{ Resource: resource, Action: "*", }) } return accessRecords }
func MeterRequests(reg metrics.Registry) func(http.Handler) http.Handler { return func(back http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { start := time.Now() writer := statusResponseWriter{w, 200} back.ServeHTTP(writer, req) route := mux.CurrentRoute(req) if name := route.GetName(); name != "" { timer := metrics.GetOrRegisterTimer(name, reg) timer.UpdateSince(start) meter := metrics.GetOrRegisterMeter(fmt.Sprintf("%s.%d", name, writer.status), reg) meter.Mark(1) } }) } }
func (a *App) renderTemplate(w http.ResponseWriter, r *http.Request, name string, status int, data interface{}) error { a.tmplLock.Lock() defer a.tmplLock.Unlock() if a.tmpls == nil || ReloadTemplates { if err := a.parseHTMLTemplates(templates); err != nil { return err } } w.WriteHeader(status) if ct := w.Header().Get("content-type"); ct == "" { w.Header().Set("Content-Type", "text/html; charset=utf-8") } t := a.tmpls[name] if t == nil { return fmt.Errorf("Template %s not found", name) } if data != nil { // Set TemplateCommon values. baseURL, err := a.URLTo(RootRoute) if err != nil { return err } reflect.ValueOf(data).Elem().FieldByName("TemplateCommon").Set(reflect.ValueOf(TemplateCommon{ CurrentRoute: mux.CurrentRoute(r).GetName(), CurrentURI: r.URL, BaseURL: baseURL, })) } // Write to a buffer to properly catch errors and avoid partial output written to the http.ResponseWriter var buf bytes.Buffer err := t.Execute(&buf, data) if err != nil { return err } _, err = buf.WriteTo(w) return err }
// nameRequired returns true if the route requires a name. func (app *App) nameRequired(r *http.Request) bool { route := mux.CurrentRoute(r) routeName := route.GetName() return route == nil || (routeName != v2.RouteNameBase && routeName != v2.RouteNameCatalog) }
func checkTestRouter(t *testing.T, testCases []routeTestCase, prefix string, deeplyEqual bool) { router := RouterWithPrefix(prefix) testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { testCase := routeTestCase{ RequestURI: r.RequestURI, Vars: mux.Vars(r), RouteName: mux.CurrentRoute(r).GetName(), } enc := json.NewEncoder(w) if err := enc.Encode(testCase); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } }) // Startup test server server := httptest.NewServer(router) for _, testcase := range testCases { testcase.RequestURI = strings.TrimSuffix(prefix, "/") + testcase.RequestURI // Register the endpoint route := router.GetRoute(testcase.RouteName) if route == nil { t.Fatalf("route for name %q not found", testcase.RouteName) } route.Handler(testHandler) u := server.URL + testcase.RequestURI resp, err := http.Get(u) if err != nil { t.Fatalf("error issuing get request: %v", err) } if testcase.StatusCode == 0 { // Override default, zero-value testcase.StatusCode = http.StatusOK } if testcase.ExpectedURI == "" { // Override default, zero-value testcase.ExpectedURI = testcase.RequestURI } if resp.StatusCode != testcase.StatusCode { t.Fatalf("unexpected status for %s: %v %v", u, resp.Status, resp.StatusCode) } if testcase.StatusCode != http.StatusOK { // We don't care about json response. continue } dec := json.NewDecoder(resp.Body) var actualRouteInfo routeTestCase if err := dec.Decode(&actualRouteInfo); err != nil { t.Fatalf("error reading json response: %v", err) } // Needs to be set out of band actualRouteInfo.StatusCode = resp.StatusCode if actualRouteInfo.RequestURI != testcase.ExpectedURI { t.Fatalf("URI %v incorrectly parsed, expected %v", actualRouteInfo.RequestURI, testcase.ExpectedURI) } if actualRouteInfo.RouteName != testcase.RouteName { t.Fatalf("incorrect route %q matched, expected %q", actualRouteInfo.RouteName, testcase.RouteName) } // when testing deep equality, the actualRouteInfo has an empty ExpectedURI, we don't want // that to make the comparison fail. We're otherwise done with the testcase so empty the // testcase.ExpectedURI testcase.ExpectedURI = "" if deeplyEqual && !reflect.DeepEqual(actualRouteInfo, testcase) { t.Fatalf("actual does not equal expected: %#v != %#v", actualRouteInfo, testcase) } } }
// TestRouter registers a test handler with all the routes and ensures that // each route returns the expected path variables. Not method verification is // present. This not meant to be exhaustive but as check to ensure that the // expected variables are extracted. // // This may go away as the application structure comes together. func TestRouter(t *testing.T) { router := Router() testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { testCase := routeTestCase{ RequestURI: r.RequestURI, Vars: mux.Vars(r), RouteName: mux.CurrentRoute(r).GetName(), } enc := json.NewEncoder(w) if err := enc.Encode(testCase); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } }) // Startup test server server := httptest.NewServer(router) for _, testcase := range []routeTestCase{ { RouteName: RouteNameBase, RequestURI: "/v2/", Vars: map[string]string{}, }, { RouteName: RouteNameManifest, RequestURI: "/v2/foo/manifests/bar", Vars: map[string]string{ "name": "foo", "reference": "bar", }, }, { RouteName: RouteNameManifest, RequestURI: "/v2/foo/bar/manifests/tag", Vars: map[string]string{ "name": "foo/bar", "reference": "tag", }, }, { RouteName: RouteNameTags, RequestURI: "/v2/foo/bar/tags/list", Vars: map[string]string{ "name": "foo/bar", }, }, { RouteName: RouteNameBlob, RequestURI: "/v2/foo/bar/blobs/tarsum.dev+foo:abcdef0919234", Vars: map[string]string{ "name": "foo/bar", "digest": "tarsum.dev+foo:abcdef0919234", }, }, { RouteName: RouteNameBlob, RequestURI: "/v2/foo/bar/blobs/sha256:abcdef0919234", Vars: map[string]string{ "name": "foo/bar", "digest": "sha256:abcdef0919234", }, }, { RouteName: RouteNameBlobUpload, RequestURI: "/v2/foo/bar/blobs/uploads/", Vars: map[string]string{ "name": "foo/bar", }, }, { RouteName: RouteNameBlobUploadChunk, RequestURI: "/v2/foo/bar/blobs/uploads/uuid", Vars: map[string]string{ "name": "foo/bar", "uuid": "uuid", }, }, { RouteName: RouteNameBlobUploadChunk, RequestURI: "/v2/foo/bar/blobs/uploads/D95306FA-FAD3-4E36-8D41-CF1C93EF8286", Vars: map[string]string{ "name": "foo/bar", "uuid": "D95306FA-FAD3-4E36-8D41-CF1C93EF8286", }, }, { RouteName: RouteNameBlobUploadChunk, RequestURI: "/v2/foo/bar/blobs/uploads/RDk1MzA2RkEtRkFEMy00RTM2LThENDEtQ0YxQzkzRUY4Mjg2IA==", Vars: map[string]string{ "name": "foo/bar", "uuid": "RDk1MzA2RkEtRkFEMy00RTM2LThENDEtQ0YxQzkzRUY4Mjg2IA==", }, }, { // Check ambiguity: ensure we can distinguish between tags for // "foo/bar/image/image" and image for "foo/bar/image" with tag // "tags" RouteName: RouteNameManifest, RequestURI: "/v2/foo/bar/manifests/manifests/tags", Vars: map[string]string{ "name": "foo/bar/manifests", "reference": "tags", }, }, { // This case presents an ambiguity between foo/bar with tag="tags" // and list tags for "foo/bar/manifest" RouteName: RouteNameTags, RequestURI: "/v2/foo/bar/manifests/tags/list", Vars: map[string]string{ "name": "foo/bar/manifests", }, }, { RouteName: RouteNameBlobUploadChunk, RequestURI: "/v2/foo/../../blob/uploads/D95306FA-FAD3-4E36-8D41-CF1C93EF8286", StatusCode: http.StatusNotFound, }, } { // Register the endpoint router.GetRoute(testcase.RouteName).Handler(testHandler) u := server.URL + testcase.RequestURI resp, err := http.Get(u) if err != nil { t.Fatalf("error issuing get request: %v", err) } if testcase.StatusCode == 0 { // Override default, zero-value testcase.StatusCode = http.StatusOK } if resp.StatusCode != testcase.StatusCode { t.Fatalf("unexpected status for %s: %v %v", u, resp.Status, resp.StatusCode) } if testcase.StatusCode != http.StatusOK { // We don't care about json response. continue } dec := json.NewDecoder(resp.Body) var actualRouteInfo routeTestCase if err := dec.Decode(&actualRouteInfo); err != nil { t.Fatalf("error reading json response: %v", err) } // Needs to be set out of band actualRouteInfo.StatusCode = resp.StatusCode if actualRouteInfo.RouteName != testcase.RouteName { t.Fatalf("incorrect route %q matched, expected %q", actualRouteInfo.RouteName, testcase.RouteName) } if !reflect.DeepEqual(actualRouteInfo, testcase) { t.Fatalf("actual does not equal expected: %#v != %#v", actualRouteInfo, testcase) } } }
// nameRequired returns true if the route requires a name. func (app *App) nameRequired(r *http.Request) bool { route := mux.CurrentRoute(r) return route == nil || route.GetName() != v2.RouteNameBase }