wykonywanie niestandardowych żądań
do tej pory nauczyliśmy się tworzyć proste żądania HTTP, ale nie skupialiśmy się zbytnio na dostosowywaniu żądań, takich jak ustawianie niestandardowych nagłówków żądań lub tworzenie PUT, PATCH I DELETE (i inne) żądania HTTP.
http.Struktura żądania
strukturahttp.Request konfiguruje żądanie do wysłania., Get,Post I Inne metody wystawione przez*http.Client faktycznie konstruują obiekthttp.Request wewnętrznie, aby wysłać żądanie.
ta struktura ma wiele pól do konfiguracji połączenia TLS, połączenia keep-alive, danych formularza i innych ustawień, ale poniższe pola są minimalną konfiguracją, z którą możemy pracować.
Więcej informacji o znajdziesz tutaj.,
struktura*http.Request implementuje wiele metod do modyfikacji obiektu request przed jego wysłaniem. Metoda*Request.AddCookie dodaje plik cookie do obiektu żądania i *Request.SetBasicAuth ustawia podstawowy nagłówek autoryzacji żądania. Możesz zbadać te metody stąd.
gdy zbudujemy obiekt request, musimy wykonać żądanie z tym obiektem request ręcznie. W tym celu musimy użyć metody *Client.Do. Ponieważ Go dostarcza http.DefaultClient, możemy użyć go do złożenia żądania.,
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.,
treść żądania przechowywana w polu Request.Bodypowinna być obiektem implementującym interfejs io.ReadCloser(Grupa interfejsów io.ReaderI io.Closer). Funkcjastrings.NewReader zwraca obiektio.Reader Iioutil.NopCloser dodaje metodęClose() w obiekcieio.Reader.
metodaClose dodana przezNopCloser funkcja nic nie robi, po prostu zwraca błądnil., Ciało żądania jest zamknięte dla We/Wy poprzez wywołanie metody Close() podczas wysyłania żądania. W rzeczywistym przypadku użycia należy poprawnie zaimplementować metodę Close, aby wyłączyć I/O w treści żądania.
zainicjowaliśmy również poleHeader z niektórymi początkowymi nagłówkami żądań. Aby wysłać żądanie, używamy metody DefaultClient.Do, która zwraca odpowiedź sieci i błąd non-nil, jeśli żądanie się nie powiedzie.,
🌶 go run go-http-client.go
status: 200
body: {"status":"success","data":{"name":"test","salary":"123","age":"23","id":53}}
zgadzam się, wysyłanie niestandardowego żądania wydaje się dość skomplikowane, ale możemy użyć funkcjihttp.NewRequest do zbudowania obiektu*http.Request z kilku prostych wartości, które mają następującą składnię.
func NewRequest(method, url string, body io.Reader) (*Request, error)
Ta funkcja zwraca*http.Request obiekt Inon-nil błąd, jeśli niektóre wartości argumentów nie są poprawne. Jeśli argument method jest pusty, przyjmuje się żądanie GET., We can add headers to the returned *Request object.

The program above returns the same response as the earlier example., Mimo żereqBody nie implementujeio.Closer interfejs, powinien idealnie zaimplementować poprawnąClose metodę, która wyłącza I/O, w przeciwnym razie Go dodaje metodę Zamknięcia Bez op za pomocąioutil.NopCloser funkcja.
http.Struktura klienta
strukturahttp.Client tworzy klienta HTTP z pewną konfiguracją, która może wysyłać żądania HTTP. http.DefaultClient jest wskaźnikiem do pustego obiektuhttp.Client, który wyświetla domyślnego klienta HTTP.,
var DefaultClient = &http.Client{}
jak widzieliśmy wcześniej, *http.Client implementuje Get, Post, PostForm, Head I Do metody. Zobaczmy, jak wygląda typ struktury 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
}
poleTransport obiekt, który implementuje metodęRoundTrip. Obiekt ten jest odpowiedzialny za wykonanie pojedynczego żądania HTTP i zwrócenie odpowiedzi., Jeśli wartość tego pola wynosi nil, to jest używane http.DefaultTransport typu *http.Transport. W większości przypadków ta wartość domyślna jest dla nas wystarczająco dobra.
poleCheckRedirect jest funkcją, która sprawdza, czy należy postępować zgodnie z przekierowaniem wymaganym przez odpowiedź. Jeśli ta wartość to nil, używana jest domyślna Polityka maksymalnego przekierowania 10.
argumentreq jest najnowszym żądaniem, a argumentvia zawiera starsze żądania (w starej pierwszej kolejności)., Jeśli ta funkcja zwróci błąd non-nil, próba przekierowania zostanie zablokowana. Sprawdź tę dokumentację, aby dowiedzieć się więcej o sposobie zwracania odpowiedzi i typach błędów.
poleJar określa mechanizm dodawania plików cookie do wychodzących żądań HTTP i plików cookie pamięci podręcznej z przychodzących odpowiedzi. Ten plik cookie jest konsultowany dla każdego wychodzącego i przekierowanego żądania.
Jeśli ta wartość tonil, pliki cookie są wysyłane tylko wtedy, gdy zostały określone w żądaniu (i skopiowane do przekierowanych żądań)., W przypadku przekierowania żądania cookie jar może mutować wartości pliku cookie. Możesz użyć pakietu net/http/cookiejar, aby utworzyć niestandardowy słoik cookie.
poleTimeout określa limit czasu, przed którym należy odczytać odpowiedź. If wartość pola if 0 co oznacza, że klient HTTP nie ma limitu czasu. Wartość ta wskazuje czas do pełnego odczytania ostatecznej odpowiedzi, która obejmuje wszystkie przekierowania i odczyt odpowiedzi.,
⚠ ️ ponieważ domyślną wartością
Timeoutjest0, może to być niebezpieczne w niektórych scenariuszach, w których złośliwa usługa nigdy nie wysyła odpowiedzi, wyczerpując przepustowość i powodując inne problemy. Dlatego pamiętaj, aby dodać pewien czas dla każdego żądania, które pochodzi z twojego komputera.
aby sprawdzić, czy błąd zwracany przez*Client.Get(lub inną metodę) wynika z limitu czasu, powinniśmy sprawdzićerr.Timeout() wartość., Jeśli timeout wystąpi podczas czytania ciała odpowiedzi, zwróci błąd.
stwórzmy nowego klienta z małą wartością timeout i wyślij proste zapytanie HTTPGET. Ustawimy wartość timeout 100 milliseconds I ponieważ istnieje duże prawdopodobieństwo wystąpienia timeoutu żądania, sprawdzimy również błąd 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.,
ponieważ błąd zwracany przezGet metoda (i inne metody) jest zawsze typu*url.Error, musimy wyodrębnić tę konkretną wartość z err, który jest typu error interfejs.
gdy błąd wystąpi z powodu limitu czasu, metoda*Error.Temporary() zwracatrue. Z poniższego wyniku widzimy, że błąd zwracany przezGet jest rzeczywiście spowodowany timeoutem.