DataSource.Http

DataSource.Http requests are an alternative to doing Elm HTTP requests the traditional way using the elm/http package.

The key differences are:

  • DataSource.Http.Requests are performed once at build time (Http.Requests are performed at runtime, at whenever point you perform them)
  • DataSource.Http.Requests have a built-in DataSource.andThen that allows you to perform follow-up requests without using tasks

Scenarios where DataSource.Http is a good fit

If you need data that is refreshed often you may want to do a traditional HTTP request with the elm/http package. The kinds of situations that are served well by static HTTP are with data that updates moderately frequently or infrequently (or never). A common pattern is to trigger a new build when data changes. Many JAMstack services allow you to send a WebHook to your host (for example, Netlify is a good static file host that supports triggering builds with webhooks). So you may want to have your site rebuild everytime your calendar feed has an event added, or whenever a page or article is added or updated on a CMS service like Contentful.

In scenarios like this, you can serve data that is just as up-to-date as it would be using elm/http, but you get the performance gains of using DataSource.Http.Requests as well as the simplicity and robustness that comes with it. Read more about these benefits in this article introducing DataSource.Http requests and some concepts around it.

Scenarios where DataSource.Http is not a good fit

  • Data that is specific to the logged-in user
  • Data that needs to be the very latest and changes often (for example, sports scores)
type alias RequestDetails =
{ url : String
, method : String
, headers : List ( String, String )
, body : Body
}

The full details to perform a DataSource.Http request.

get : String -> Decoder a -> DataSource a

A simplified helper around DataSource.Http.request, which builds up a DataSource.Http GET request.

import DataSource
import DataSource.Http
import Json.Decode as Decode exposing (Decoder)

getRequest : DataSource Int
getRequest =
    DataSource.Http.get
        "https://api.github.com/repos/dillonkearns/elm-pages"
        (Decode.field "stargazers_count" Decode.int)
request : RequestDetails -> Expect a -> DataSource a

Decoding Request Body

type Expect value

Analogous to the Expect type in the elm/http package. This represents how you will process the data that comes back in your DataSource.Http request.

You can derive ExpectJson from ExpectString. Or you could build your own helper to process the String as XML, for example, or give an elm-pages build error if the response can't be parsed as XML.

Gives the HTTP response body as a raw String.

import DataSource exposing (DataSource)
import DataSource.Http

request : DataSource String
request =
    DataSource.Http.request
        { url = "https://example.com/file.txt"
        , method = "GET"
        , headers = []
        , body = DataSource.Http.emptyBody
        }
        DataSource.Http.expectString
expectJson : Decoder value -> Expect value

Handle the incoming response as JSON and don't optimize the asset and strip out unused values. Be sure to use the DataSource.Http.request function if you want an optimized request that strips out unused JSON to optimize your asset size. This function makes sense to use for things like a GraphQL request where the JSON payload is already trimmed down to the data you explicitly requested.

If the function you pass to expectString yields an Err, then you will get a build error that will fail your elm-pages build and print out the String from the Err.

expectBytes : Decoder value -> Expect value
expectWhatever : value -> Expect value

Expecting Responses

type Response body
= BadUrl_ String
| Timeout_
| NetworkError_
| BadStatus_ Metadata body
| GoodStatus_ Metadata body
type alias Metadata =
{ url : String
, statusCode : Int
, statusText : String
, headers : Dict String String
}
type Error
= BadUrl String
| Timeout
| NetworkError
| BadStatus Metadata String
| BadBody String

Building a DataSource.Http Request Body

The way you build a body is analogous to the elm/http package. Currently, only emptyBody and stringBody are supported. If you have a use case that calls for a different body type, please open a Github issue and describe your use case!

type alias Body =
Body

A body for a DataSource.Http request.

emptyBody : Body

Build an empty body for a DataSource.Http request. See elm/http's Http.emptyBody.

stringBody : String -> String -> Body

Builds a string body for a DataSource.Http request. See elm/http's Http.stringBody.

Note from the elm/http docs:

The first argument is a MIME type of the body. Some servers are strict about this!

jsonBody : Value -> Body

Builds a JSON body for a DataSource.Http request. See elm/http's Http.jsonBody.

Uncached Requests

uncachedRequest : RequestDetails -> Expect a -> DataSource a