http-client

repository·main·Indexed 43 days ago

https://github.com/snoyberg/http-client

A tiered Haskell HTTP client ecosystem featuring a low-level engine (http-client), high-level conduit-based APIs (http-conduit), and SSL/TLS backends including http-client-tls and http-client-openssl.

Tokens
5.7K
Snippets
17
Records
24
Agent score
55%

What's inside http-client

  1. Overview of http-conduit

    main

    The http-conduit library provides tools for making efficient HTTP and HTTPS requests in Haskell. It offers two primary modes of operation:

    1. Simple Interface: For standard request/response patterns where the entire body is handled at once.
    2. Streaming Interface: For high-performance or memory-efficient handling of large request or response bodies using streaming techniques.

    Note: The Network.HTTP.Conduit.Browser module is no longer part of this package and has been moved to the standalone http-conduit-browser package on Hackage.

  2. Overview of the http-client family of packages

    main

    The http-client megarepo contains a family of Haskell packages for HTTP communication, ranging from low-level engines to high-level convenience APIs:

    • http-client: The core low-level HTTP client engine.
    • http-client-tls and http-client-openssl: Backends that provide SSL/TLS support for the engine.
    • http-conduit: A high-level API built on top of the core engine for improved user convenience.

    For a practical guide on how to use these packages, refer to the TUTORIAL.md file in the repository.

  3. Overview of the http-client engine

    main

    The http-client library serves as a low-level HTTP client engine designed to act as a base layer for higher-level, more user-friendly packages. It is a refactored version of http-conduit.

    Important Security Note: To enable secure HTTPS connections, you must use the http-client-tls package in conjunction with this library.

  4. Use http-client-openssl for secure connections via OpenSSL

    main

    The http-client-openssl package provides an alternative to http-client-tls for developers who need to make secure HTTPS connections using the OpenSSL library instead of the default TLS implementation.

    For general usage and full tutorials on the broader http-client package ecosystem, refer to the official Haskell documentation at https://haskell-lang.org/library/http-client.

  5. Understand version mapping between http-client and http-conduit

    main

    Because Haddock documentation for the family of packages often pulls directly from http-client, the Since version notations in documentation may refer to the http-client version rather than the http-conduit version.

    Use the following mapping to correlate versions:

    • http-client-0.5.0 $\approx$ http-conduit-2.2.0
    • http-client-0.4.30 $\approx$ http-conduit-2.1.11
  6. Share the Manager to optimize connection pooling

    main

    Initializing a Manager has a small cost, and each Manager maintains its own independent pool of connections. To reduce TCP handshake overhead and prevent exhausting connections to a single server, you should create a single Manager and share it throughout your entire application.

    In a concurrent environment, pass the same Manager instance to all worker threads or asynchronous actions.

    main :: IO ()
    main = do
        -- Create the manager once
        manager <- newManager tlsManagerSettings
    
        -- Share the same manager across concurrent actions
        runConcurrently $ sequenceA_ $ replicate 16
                        $ Concurrently $ doSomething manager
    
    doSomething :: Manager -> IO ()
    doSomething manager = do
        let request = "http://httpbin.org/get"
        response <- httpLbs request manager
        -- ... process response
  7. How Connection Managers work

    main

    A Manager handles the lifecycle of connections, including connection reuse (to reduce TCP overhead) and secure connection (HTTPS) configuration.

    • Network.HTTP.Simple uses a shared global Manager by default.
    • You can create a custom Manager using newManager and apply it to specific requests using setRequestManager.
    • For full HTTP and HTTPS support, use tlsManagerSettings from Network.HTTP.Client.TLS.
    import           Network.HTTP.Client        (defaultManagerSettings, newManager)
    import           Network.HTTP.Client.TLS     (tlsManagerSettings)
    import           Network.HTTP.Simple
    
    -- Using a custom manager for a specific request
    main :: IO ()
    main = do
        manager <- newManager defaultManagerSettings
        let request = setRequestManager manager "http://httpbin.org/get"
        response <- httpLBS request
        print (getResponseStatusCode response)
  8. Understand exception behavior for non-2XX responses

    main

    The behavior regarding non-2XX status codes depends on how the Request was constructed. This is controlled by the checkResponse setting:

    • parseUrlThrow: Produces requests that will throw an exception if the response has a non-2XX status code.
    • parseRequest: Produces "safe" requests that will not throw on non-2XX status codes.
    • parseRequest_: Similar to parseRequest, but will throw a runtime exception if the input string is malformed. This is the mechanism used by string literals via the IsString instance.

    Note: By default, http-client respects http_proxy and https_proxy environment variables.

  9. Handling non-2XX responses

    main
    In http-client version 0.5 and later, non-2XX status codes do not automatically throw exceptions. Instead, you can use the checkResponse record selector to define custom logic for inspecting the request and response and throwing exceptions if necessary.
  10. Overriding proxy settings

    main

    By default, the library respects http_proxy and https_proxy environment variables. You can override this behavior in two ways:

    1. Per-request: Use setRequestProxy (in Network.HTTP.Simple) or modify the proxy field of a Request (in Network.HTTP.Client).
    2. Via Manager: Configure the Manager settings using managerSetProxy.

    Note: If both a manager-level proxy and a request-level proxy are set, the manager setting takes precedence.

    -- Per-request override using Network.HTTP.Simple
    let request = setRequestProxy (Just (Proxy "127.0.0.1" 3128)) $ "https://httpbin.org/get"
    
    -- Per-request override using Network.HTTP.Client
    let request = "http://httpbin.org/get" { proxy = Just $ Proxy "127.0.0.1" 3128 }
    
    -- Manager-level override
    manager <- newManager $ managerSetProxy noProxy tlsManagerSettings
  11. Catching connection and HTTP exceptions

    main

    When performing network operations, connections may fail. To handle these errors, catch the HttpException type using Control.Exception.try.

    import           Control.Exception          (try)
    import           Network.HTTP.Simple
    
    main :: IO ()
    main = do
        eresponse <- try $ httpLBS "http://does-not-exist"
    
        case eresponse of
            Left e -> print (e :: HttpException)
            Right response -> print (getResponseBody response)
  12. Modify requests using setter functions

    main

    You can customize a Request using various setter functions. Common setters include:

    • setRequestMethod: Set the HTTP method (e.g., "PUT", "POST").
    • setRequestPath: Set the request path.
    • setRequestQueryString: Set query parameters.
    • setRequestBodyLBS: Set the request body from a lazy ByteString.
    • setRequestSecure: Enable HTTPS.
    • setRequestPort: Set the port number.
    • setRequestHost: Set the host.

    You can also build a request entirely programmatically starting from defaultRequest without any URL parsing.

    import           Network.HTTP.Simple
    
    main :: IO ()
    main = do
        let request = setRequestPath "/get"
                    $ setRequestHost "httpbin.org"
                    $ defaultRequest
        response <- httpJSON request
        -- ... handle response