| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package http |
| |
| import ( |
| "context" |
| "net" |
| "net/http" |
| "net/url" |
| ) |
| |
| // Request represents the HTTP request received by APISIX. |
| // We don't use net/http's Request because it doesn't suit our purpose. |
| // Take `Request.Header` as an example: |
| // |
| // 1. We need to record any change to the request headers. As the Request.Header |
| // is not an interface, there is not way to inject our special tracker. |
| // |
| // 2. As the author of fasthttp pointed out, "headers are stored in a map[string][]string. |
| // So the server must parse all the headers, ...". The official API is suboptimal, which |
| // is even worse in our case as it is not a real HTTP server. |
| type Request interface { |
| // ID returns the request id |
| ID() uint32 |
| |
| // SrcIP returns the client's IP |
| SrcIP() net.IP |
| // Method returns the HTTP method (GET, POST, PUT, etc.) |
| Method() string |
| // Path returns the path part of the client's URI (without query string and the other parts) |
| // It won't be equal to the one in the Request-Line sent by the client if it has |
| // been rewritten by APISIX |
| Path() []byte |
| // SetPath is the setter for Path |
| SetPath([]byte) |
| // Header returns the HTTP headers |
| Header() Header |
| // Args returns the query string |
| Args() url.Values |
| |
| // Var returns the value of a Nginx variable, like `r.Var("request_time")` |
| // |
| // To fetch the value, the runner will look up the request's cache first. If not found, |
| // the runner will ask it from the APISIX. If the RPC call is failed, an error in |
| // pkg/common.ErrConnClosed type is returned. |
| Var(name string) ([]byte, error) |
| |
| // Body returns HTTP request body |
| // |
| // To fetch the value, the runner will look up the request's cache first. If not found, |
| // the runner will ask it from the APISIX. If the RPC call is failed, an error in |
| // pkg/common.ErrConnClosed type is returned. |
| Body() ([]byte, error) |
| |
| // Context returns the request's context. |
| // |
| // The returned context is always non-nil; it defaults to the |
| // background context. |
| // |
| // For run plugin, the context controls cancellation. |
| Context() context.Context |
| // RespHeader returns an http.Header which allows you to add or set response headers before reaching the upstream. |
| // Some built-in headers would not take effect, like `connection`,`content-length`,`transfer-encoding`,`location,server`,`www-authenticate`,`content-encoding`,`content-type`,`content-location` and `content-language` |
| RespHeader() http.Header |
| } |
| |
| // Response represents the HTTP response from the upstream received by APISIX. |
| // In order to avoid semantic misunderstanding, |
| // we also use Response to represent the rewritten response from Plugin Runner. |
| // Therefore, any instance that implements the Response interface will be readable and rewritable. |
| type Response interface { |
| // ID returns the request id |
| ID() uint32 |
| |
| // StatusCode returns the response code |
| StatusCode() int |
| |
| // Header returns the response header. |
| // |
| // It allows you to add or set response headers before reaching the client. |
| Header() Header |
| |
| // Var returns the value of a Nginx variable, like `r.Var("request_time")` |
| // |
| // To fetch the value, the runner will look up the request's cache first. If not found, |
| // the runner will ask it from the APISIX. If the RPC call is failed, an error in |
| // pkg/common.ErrConnClosed type is returned. |
| Var(name string) ([]byte, error) |
| |
| // ReadBody returns origin HTTP response body |
| // |
| // To fetch the value, the runner will look up the request's cache first. If not found, |
| // the runner will ask it from the APISIX. If the RPC call is failed, an error in |
| // pkg/common.ErrConnClosed type is returned. |
| // |
| // It was not named `Body` |
| // because `Body` was already occupied in earlier interface implementations. |
| ReadBody() ([]byte, error) |
| |
| // Write rewrites the origin response data. |
| // |
| // Unlike `ResponseWriter.Write`, we don't need to WriteHeader(http.StatusOK) |
| // before writing the data |
| // Because APISIX will convert code 0 to 200. |
| Write(b []byte) (int, error) |
| |
| // WriteHeader rewrites the origin response StatusCode |
| // |
| // WriteHeader can't override written status. |
| WriteHeader(statusCode int) |
| } |
| |
| // Header is like http.Header, but only implements the subset of its methods |
| type Header interface { |
| // Set sets the header entries associated with key to the single element value. |
| // It replaces any existing values associated with key. |
| // The key is case insensitive |
| Set(key, value string) |
| // Del deletes the values associated with key. The key is case insensitive |
| Del(key string) |
| // Get gets the first value associated with the given key. |
| // If there are no values associated with the key, Get returns "". |
| // It is case insensitive |
| Get(key string) string |
| // View returns the internal structure. It is expected for read operations. Any write operation |
| // won't be recorded |
| View() http.Header |
| |
| // TODO: support Add |
| } |