Fare richieste su misura
finora abbiamo imparato come fare delle semplici richieste HTTP, ma l’abbiamo non concentrarsi troppo su richiesta di personalizzazione come impostazione personalizzata intestazioni di richiesta o fare PUT
PATCH
e DELETE
(e altri) le richieste HTTP.
http.Struttura della richiesta
La strutturahttp.Request
configura la richiesta da inviare., IlGet
,Post
e altri metodi esposti dal*http.Client
effettivamente costruirehttp.Request
oggetto internamente per inviare la richiesta.
Questa struttura ha più campi per configurare la connessione TLS, la connessione keep-alive, i dati del modulo e altre impostazioni, ma i seguenti campi sono una configurazione minima con cui possiamo lavorare.
can Puoi leggere di più su
Request
struct da qui.,
La struttura *http.Request
implementa molti metodi per modificare l’oggetto request prima che venga inviato. Il metodo*Request.AddCookie
aggiunge un cookie all’oggetto richiesta e*Request.SetBasicAuth
imposta l’intestazione di autorizzazione di base sulla richiesta. È possibile esplorare questi metodi da qui.
Una volta costruito un oggetto request, dobbiamo fare una richiesta con questo oggetto request manualmente. Per questo, dobbiamo usare il metodo*Client.Do
. Poiché Go fornisce http.DefaultClient
, possiamo usarlo per fare una richiesta.,
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.,
Il corpo della richiesta memorizzato nel campo Request.Body
deve essere un oggetto che implementa l’interfaccia io.ReadCloser
(un gruppo di interfacce io.Reader
e io.Closer
). strings.NewReader
restituisce un io.Reader
oggetto e ioutil.NopCloser
funzione aggiunge Close()
metodo io.Reader
oggetto.
Il metodoClose
aggiunto dalla funzioneNopCloser
non fa nulla, restituisce semplicemente un errore nil
., Il corpo della richiesta viene chiuso per I/O tramite questa chiamata al metodoClose()
quando viene inviata la richiesta. In un caso d’uso reale, è necessario implementare correttamente il metodo Close
per disabilitare l’I/O sul corpo della richiesta.
Abbiamo anche inizializzato il campo Header
con alcune intestazioni di richiesta iniziale. Per inviare la richiesta, stiamo utilizzando il metodoDefaultClient.Do
che restituisce la risposta di rete e un errore non-nil
se la richiesta non riesce.,
🌶 go run go-http-client.go
status: 200
body: {"status":"success","data":{"name":"test","salary":"123","age":"23","id":53}}
Sono d’accordo, l’invio di una richiesta personalizzata sembra piuttosto complicato ma possiamo usare la funzione http.NewRequest
per costruire *http.Request
da alcuni valori semplici che hanno la seguente sintassi.
func NewRequest(method, url string, body io.Reader) (*Request, error)
Questa funzione restituisce un oggetto*http.Request
e un errorenon-nil
nel caso in cui alcuni valori di argomento non siano validi. Se l’argomentomethod
è vuoto, si assume la richiestaGET
., We can add headers to the returned *Request
object.
The program above returns the same response as the earlier example., Anche se reqBody
non implementa l’interfaccia io.Closer
, dovrebbe idealmente implementare un metodo valido Close
che disabilita l’I/O, else, Go aggiunge un metodo di chiusura no-op su di esso utilizzando la funzione ioutil.NopCloser
.
http.Struttura client
La strutturahttp.Client
crea un client HTTP con alcune configurazioni in grado di inviare richieste HTTP. Ilhttp.DefaultClient
è un puntatore a un oggetto vuotohttp.Client
che espone un client HTTP predefinito.,
var DefaultClient = &http.Client{}
Come abbiamo visto prima, il *http.Client
implementa Get
Post
PostForm
Head
e Do
metodi. Vediamo come appare il tipo di struttura 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
}
Il campo Transport
un oggetto che implementa il metodo RoundTrip
. Questo oggetto è responsabile di eseguire una singola richiesta HTTP e restituire una risposta., Se questo valore di campo ènil
,http.DefaultTransport
di tipo*http.Transport
viene utilizzato. Nella maggior parte dei casi, questo valore predefinito è abbastanza buono per noi.
Il campo CheckRedirect
è una funzione che controlla se il reindirizzamento richiesto da una risposta deve essere seguito. Se questo valore è nil
, viene utilizzato il criterio predefinito dei reindirizzamenti massimi 10
.
L’argomentoreq
è la richiesta più recente e l’argomentovia
contiene le richieste più vecchie (nel vecchio primo ordine)., Se questa funzione restituisce un errorenon-nil
, il tentativo di reindirizzamento viene bloccato. Controlla questa documentazione per saperne di più su come viene restituita la risposta e sui tipi di errore.
Il campo Jar
specifica un meccanismo per aggiungere cookie alle richieste HTTP in uscita e cookie di cache dalle risposte in entrata. Questo cookie jar viene consultato per ogni richiesta in uscita e reindirizzata.
Se questo valore è nil
, i cookie vengono inviati solo se vengono specificati nella richiesta (e copiati nelle richieste reindirizzate)., Nel caso di una richiesta reindirizzata, cookie jar può modificare i valori del cookie. È possibile utilizzare il pacchettonet/http/cookiejar
per creare il barattolo dei cookie personalizzato.
Il campo Timeout
specifica il limite di tempo prima del quale la risposta deve essere letta. Se il valore del campo if 0
che significa che non vi è alcun timeout implementato dal client HTTP. Questo valore indica il tempo fino a quando la risposta finale è completamente letta che include tutti i reindirizzamenti e la lettura della risposta.,
⚠️ Poiché il valore predefinito del campo
Timeout
è0
, potrebbe essere pericoloso in alcuni scenari in cui un servizio dannoso non invia mai una risposta, esaurendo la larghezza di banda e causando altri problemi. Quindi assicurati di aggiungere un po ‘ di timeout per ogni richiesta che proviene dalla tua macchina.
Per verificare se l’errore restituito dal*Client.Get
(o qualsiasi altro metodo) è dovuto al timeout, dovremmo controllareerr.Timeout()
valore., Se il timeout si verifica durante la lettura del corpo della risposta, restituirà un errore.
Creiamo un nuovo client con un piccolo valore di timeout e inviamo una semplice richiesta HTTP GET
. Imposteremo il valore di timeout 100 milliseconds
e poiché c’è un’alta probabilità di timeout della richiesta, verificheremo anche un errore di timeout.,
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.,
Poiché l’errore restituito dal metodo Get
(e altri metodi) è sempre del tipo di *url.Error
, dobbiamo estrarre questo valore concreto dal err
che è del tipo error
div > interfaccia.
Quando l’errore si verifica a causa di un timeout, il metodo*Error.Temporary()
restituiscetrue
. E dal risultato seguente, possiamo vedere che l’errore restituito dal metodo Get
è effettivamente a causa di un timeout.