hacer solicitudes personalizadas
hasta ahora hemos aprendido a hacer solicitudes HTTP simples, pero no nos centramos demasiado en la personalización de solicitudes, como configurar encabezados de solicitud personalizados o hacer PUT
, PATCH
y DELETE
(y otros) peticiones HTTP.
http.Estructura de la solicitud
la estructura http.Request
configura la solicitud a enviar., El Get
, Post
y otros métodos expuestos por el *http.Client
en realidad se construyen http.Request
objeto internamente para enviar la solicitud.
esta estructura tiene varios campos para configurar la conexión TLS, la conexión keep-alive, los datos del formulario y otras configuraciones, pero los siguientes campos son una configuración mínima con la que podemos trabajar.
You puede leer más sobre
Request
struct desde aquí.,
la estructura *http.Request
implementa muchos métodos para modificar el objeto de solicitud antes de que se envíe. El método *Request.AddCookie
agrega una cookie en el objeto de solicitud y *Request.SetBasicAuth
establece el encabezado de autorización básica en la solicitud. Puede explorar estos métodos desde aquí.
una vez que construimos un objeto de solicitud, necesitamos hacer una solicitud con este objeto de solicitud manualmente. Para eso, necesitamos usar el método *Client.Do
. Dado que Go proporciona http.DefaultClient
, podemos usarlo para hacer una solicitud.,
func (c *Client) Do(req *Request) (*Response, error)
In the above example, we are first creating a *url.URL
object from a URL string by using url.Parse
function. Since Request.URL
field should be an object of type *url.URL
, this step is necessary.,
El cuerpo de solicitud almacenado en Request.Body
campo debe ser un objeto que implementa io.ReadCloser
interfaz (un grupo de io.Reader
y io.Closer
interfaces). El strings.NewReader
devuelve un io.Reader
objeto y ioutil.NopCloser
función agrega Close()
método en el io.Reader
objeto.
el método Close
añadido por la función NopCloser
no hace nada, simplemente devuelve un error nil
., El cuerpo de la solicitud se cierra para E/s a través de esta llamada al método Close()
cuando se envía la solicitud. En un caso de uso del mundo real, debe implementar el método Close
correctamente para deshabilitar e / s en el cuerpo de la solicitud.
también hemos inicializado el campo Header
con algunos encabezados de solicitud iniciales. Para enviar la solicitud, estamos utilizando el método DefaultClient.Do
que devuelve la respuesta de red y un error non-nil
si la solicitud falla.,
🌶 go run go-http-client.go
status: 200
body: {"status":"success","data":{"name":"test","salary":"123","age":"23","id":53}}
estoy de acuerdo, enviar una solicitud personalizada parece bastante complicado, pero podemos usar la función http.NewRequest
para construir *http.Request
objeto a partir de algunos valores simples que tiene la siguiente sintaxis.
func NewRequest(method, url string, body io.Reader) (*Request, error)
Esta función devuelve un objeto*http.Request
y un errornon-nil
en caso de que algunos valores de argumento no sean válidos. Si el argumentomethod
está vacío, se asume la peticiónGET
., We can add headers to the returned *Request
object.
The program above returns the same response as the earlier example., Aunque reqBody
no implementa la interfaz io.Closer
, idealmente debería implementar un método Close
que deshabilite E/S, de lo contrario, Go agrega un método de cierre sin op usando la función ioutil.NopCloser
.
http.Estructura del cliente
la estructura http.Client
crea un cliente HTTP con alguna configuración que puede enviar solicitudes HTTP. El http.DefaultClient
es un puntero a un objeto http.Client
vacío que expone un cliente HTTP predeterminado.,
var DefaultClient = &http.Client{}
Como hemos visto antes, el *http.Client
implementa Get
, Post
, PostForm
, Head
y Do
métodos. Veamos cómo se ve el tipo de estructura http.Client
.
type Client struct {
// mechanism by which individual HTTP requests are made
Transport RoundTripper
// specifies the policy for handling redirects
CheckRedirect func(req *Request, via *Request) error// specifies the cookie jar
Jar CookieJar
// specifies a time limit for requests
Timeout time.Duration
}
El Transport
campo de un objeto que implementa el RoundTrip
método. Este objeto es responsable de ejecutar una única solicitud HTTP y devolver una respuesta., Si este valor de campo nil
, http.DefaultTransport
de tipo *http.Transport
se utiliza. En la mayoría de los casos, este valor predeterminado es lo suficientemente bueno para nosotros.
el campo CheckRedirect
es una función que comprueba si se debe seguir la redirección exigida por una respuesta. Si este valor es nil
, se utiliza la política predeterminada de redirecciones máximas 10
.
el argumento req
es la petición más reciente y el argumento via
contiene las peticiones más antiguas (en primer orden)., Si esta función devuelve un error non-nil
, el intento de redirección se bloquea. Consulte esta documentación para saber más sobre cómo se devuelve la respuesta y los tipos de error.
el campo Jar
especifica un mecanismo para agregar cookies en solicitudes HTTP salientes y cookies de caché de las respuestas entrantes. Este tarro de cookies se consulta para cada solicitud saliente y redirigida.
si este valor es nil
, las cookies solo se envían si se especifican en la solicitud (y se copian en las solicitudes redirigidas)., En el caso de una solicitud redirigida, cookie jar puede mutar los valores de la cookie. Puede usar el paquete net/http/cookiejar
para crear su tarro de cookies personalizado.
el campo Timeout
especifica el límite de tiempo antes del cual se debe leer la respuesta. If El valor del campo if 0
lo que significa que no hay tiempo de espera implementado por el cliente HTTP. Este valor indica el tiempo hasta que la respuesta final se lee completamente, lo que incluye todas las redirecciones y la lectura de la respuesta.,
Since️ dado que el valor predeterminado del campo
Timeout
es0
, podría ser peligroso en algunos escenarios donde un servicio malicioso nunca envía una respuesta, agotando su ancho de banda y causando otros problemas. Por lo tanto, asegúrese de agregar un tiempo de espera para cada solicitud que se origina en su máquina.
para comprobar si el error devuelto por el *Client.Get
(o cualquier otro método) se debe a tiempo de espera, debemos comprobar err.Timeout()
valor., Si el tiempo de espera se produce mientras se lee el cuerpo de la respuesta, devolverá un error.
vamos a crear un nuevo cliente con un pequeño valor de tiempo de espera y enviar una simple solicitud HTTP GET
. Estableceremos el valor de tiempo de espera 100 milliseconds
y dado que hay una alta probabilidad de tiempo de espera de solicitud, también comprobaremos si hay un error de tiempo de espera.,
In the example above, we have created an HTTP client with a timeout of 100ms
. Since Get
, Post
and other methods are implemented by the pointer of http.Client
type, the client
is a pointer.,
dado que el error devuelto por el método Get
(y otros métodos) siempre es del tipo *url.Error
, necesitamos extraer este valor concreto del err
que es del tipo error
interfaz.
cuando se produce el error debido a un tiempo de espera, el método *Error.Temporary()
devuelve true
. Y del resultado a continuación, podemos ver que el error devuelto por el método Get
es de hecho debido a un tiempo de espera.