(ctx context.Context)
| 117 | } |
| 118 | |
| 119 | func (a *APIServer) CreateRouter(ctx context.Context) *mux.Router { |
| 120 | webMux := mux.NewRouter() |
| 121 | apiMux := webMux.PathPrefix("/api").Subrouter() |
| 122 | httpAPIKeyRateLimiter := throttled.HTTPRateLimiter{ |
| 123 | DeniedHandler: http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { |
| 124 | rw.WriteHeader(429) |
| 125 | enc := json.NewEncoder(rw) |
| 126 | _ = enc.Encode(map[string]string{"error": "Too many requests using your API key"}) |
| 127 | }), |
| 128 | RateLimiter: a.apiKeyRateLimiter, |
| 129 | VaryBy: &throttled.VaryBy{ |
| 130 | Headers: []string{"X-API-Key"}, |
| 131 | }, |
| 132 | } |
| 133 | httpAddrRateLimiter := throttled.HTTPRateLimiter{ |
| 134 | DeniedHandler: http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { |
| 135 | rw.WriteHeader(429) |
| 136 | enc := json.NewEncoder(rw) |
| 137 | _ = enc.Encode(map[string]string{"error": "Too many requests from your address"}) |
| 138 | }), |
| 139 | RateLimiter: a.addrRateLimiter, |
| 140 | VaryBy: &throttled.VaryBy{ |
| 141 | Custom: func(r *http.Request) string { |
| 142 | realAddr := r.RemoteAddr |
| 143 | forwardedAddr := r.Header.Get("X-Forwarded-For") |
| 144 | if forwardedAddr != "" { |
| 145 | realAddr = forwardedAddr |
| 146 | |
| 147 | ips := strings.Split(realAddr, " ") |
| 148 | if len(ips) > 1 { |
| 149 | realAddr = ips[0] |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | return realAddr |
| 154 | }, |
| 155 | }, |
| 156 | } |
| 157 | |
| 158 | apiMux.Use(handlers.CORS( |
| 159 | handlers.AllowedHeaders([]string{"X-API-Key", "Content-Type", "Cache-Control"}), |
| 160 | handlers.AllowedMethods([]string{"GET", "HEAD", "OPTIONS"}), |
| 161 | handlers.AllowedOrigins([]string{"*"}), |
| 162 | )) |
| 163 | apiMux.Use(httpAPIKeyRateLimiter.RateLimit) |
| 164 | apiMux.Use(httpAddrRateLimiter.RateLimit) |
| 165 | apiMux.Use(func(next http.Handler) http.Handler { |
| 166 | return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { |
| 167 | key := r.Header.Get("x-api-key") |
| 168 | if _, ok := a.apiKeysMap[key]; !ok { |
| 169 | rw.Header().Add("Content-Type", "application/json") |
| 170 | rw.WriteHeader(403) |
| 171 | enc := json.NewEncoder(rw) |
| 172 | _ = enc.Encode(map[string]string{"error": "Unknown or missing X-API-Key value"}) |
| 173 | |
| 174 | return |
| 175 | } |
| 176 | next.ServeHTTP(rw, r) |
no test coverage detected