Skip to main content

Overview

Package http provides HTTP client and server implementations. Get, Head, Post, and PostForm make HTTP (or HTTPS) requests. The Client type provides more control over the HTTP client behavior.

HTTP Client

Client

Client is an HTTP client. Its zero value (DefaultClient) is a usable client that uses DefaultTransport.
type Client struct {
    Transport     RoundTripper
    CheckRedirect func(req *Request, via []*Request) error
    Jar           CookieJar
    Timeout       time.Duration
}
Transport
RoundTripper
Specifies the mechanism by which individual HTTP requests are made. If nil, DefaultTransport is used
CheckRedirect
func(req *Request, via []*Request) error
Specifies the policy for handling redirects. If nil, the default policy is to stop after 10 consecutive requests
Jar
CookieJar
Specifies the cookie jar. If nil, cookies are only sent if explicitly set on the Request
Timeout
time.Duration
Specifies a time limit for requests. Zero means no timeout

Making Requests

Get

Issues a GET request to the specified URL.
resp, err := http.Get("https://api.example.com/users")
if err != nil {
    // handle error
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
url
string
required
The URL to request
resp
*Response
The HTTP response
err
error
Error if request failed

Post

Issues a POST request to the specified URL.
resp, err := http.Post(
    "https://api.example.com/users",
    "application/json",
    bytes.NewBuffer(jsonData),
)
if err != nil {
    // handle error
}
defer resp.Body.Close()
url
string
required
The URL to request
contentType
string
required
The content type of the request body
body
io.Reader
required
The request body
resp
*Response
The HTTP response
err
error
Error if request failed

Request

Request represents an HTTP request received by a server or to be sent by a client.
req, err := http.NewRequest("POST", "https://api.example.com/users", body)
if err != nil {
    // handle error
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer token")

client := &http.Client{}
resp, err := client.Do(req)
Method
string
Specifies the HTTP method (GET, POST, PUT, DELETE, etc.)
URL
*url.URL
Specifies the URL being requested
Header
Header
Contains the request header fields
Body
io.ReadCloser
The request body

Response

Response represents the response from an HTTP request.
type Response struct {
    Status     string // e.g. "200 OK"
    StatusCode int    // e.g. 200
    Proto      string // e.g. "HTTP/1.0"
    Header     Header
    Body       io.ReadCloser
    ContentLength int64
}
Status
string
The status line (e.g., “200 OK”)
StatusCode
int
The HTTP status code (e.g., 200, 404, 500)
Header
Header
The response headers
Body
io.ReadCloser
The response body. Must be closed after reading
ContentLength
int64
The length of the response body. -1 if unknown

HTTP Server

Handler

Handler responds to an HTTP request.
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

HandlerFunc

HandlerFunc type is an adapter to allow the use of ordinary functions as HTTP handlers.
func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}

http.HandleFunc("/hello/", helloHandler)
http.ListenAndServe(":8080", nil)
pattern
string
required
The URL pattern to match
handler
func(ResponseWriter, *Request)
required
The handler function

ResponseWriter

ResponseWriter interface is used by an HTTP handler to construct an HTTP response.
type ResponseWriter interface {
    Header() Header
    Write([]byte) (int, error)
    WriteHeader(statusCode int)
}
Header
func() Header
Returns the header map that will be sent. Must be called before WriteHeader or Write
Write
func([]byte) (int, error)
Writes the data to the connection as part of an HTTP reply
WriteHeader
func(int)
Sends an HTTP response header with the provided status code

ListenAndServe

Listens on the TCP network address and then calls Serve to handle requests.
http.HandleFunc("/", indexHandler)
http.HandleFunc("/api/users", usersHandler)

log.Fatal(http.ListenAndServe(":8080", nil))
addr
string
required
The TCP address to listen on (e.g., “:8080” or “127.0.0.1:8080”)
handler
Handler
The handler to invoke. If nil, DefaultServeMux is used
err
error
Always returns a non-nil error

Server

Server defines parameters for running an HTTP server.
srv := &http.Server{
    Addr:           ":8080",
    Handler:        myHandler,
    ReadTimeout:    10 * time.Second,
    WriteTimeout:   10 * time.Second,
    MaxHeaderBytes: 1 << 20,
}

log.Fatal(srv.ListenAndServe())
Addr
string
TCP address to listen on. If empty, “:http” is used
Handler
Handler
Handler to invoke. If nil, DefaultServeMux is used
ReadTimeout
time.Duration
Maximum duration for reading the entire request
WriteTimeout
time.Duration
Maximum duration before timing out writes of the response

Examples

Simple HTTP Server

package main

import (
    "fmt"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, World!")
    })
    
    http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        fmt.Fprintf(w, `{"users": ["alice", "bob"]}`)
    })
    
    log.Println("Starting server on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

HTTP Client with Custom Headers

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

func main() {
    user := User{Name: "Alice", Email: "[email protected]"}
    jsonData, _ := json.Marshal(user)
    
    req, err := http.NewRequest("POST", "https://api.example.com/users", bytes.NewBuffer(jsonData))
    if err != nil {
        panic(err)
    }
    
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer your-token-here")
    
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    body, _ := io.ReadAll(resp.Body)
    fmt.Println("Response:", string(body))
    fmt.Println("Status:", resp.StatusCode)
}

JSON API Handler

func apiHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    
    switch r.Method {
    case "GET":
        json.NewEncoder(w).Encode(map[string]string{
            "message": "GET request received",
        })
    case "POST":
        var data map[string]interface{}
        if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
            w.WriteHeader(http.StatusBadRequest)
            json.NewEncoder(w).Encode(map[string]string{
                "error": "Invalid JSON",
            })
            return
        }
        
        w.WriteHeader(http.StatusCreated)
        json.NewEncoder(w).Encode(map[string]interface{
            "message": "Created",
            "data":    data,
        })
    default:
        w.WriteHeader(http.StatusMethodNotAllowed)
    }
}

Status Codes

Common HTTP status codes:
  • StatusOK (200) - Request succeeded
  • StatusCreated (201) - Resource created
  • StatusBadRequest (400) - Invalid request
  • StatusUnauthorized (401) - Authentication required
  • StatusForbidden (403) - Access denied
  • StatusNotFound (404) - Resource not found
  • StatusInternalServerError (500) - Server error

See Also

  • net - Low-level networking primitives
  • net/url - URL parsing

Build docs developers (and LLMs) love