StaticHttp requests are an alternative to doing Elm HTTP requests the traditional way using the elm/http package.
The key differences are:
StaticHttp.Requests are performed once at build time (Http.Requests are performed at runtime, at whenever point you perform them)StaticHttp.Requests strip out unused JSON data from the data your decoder doesn't touch to minimize the JSON payloadStaticHttp.Requests can use Pages.Secrets to securely use credentials from your environment variables which are completely masked in the production assets.StaticHttp.Requests have a built-in StaticHttp.andThen that allows you to perform follow-up requests without using tasksIf 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 StaticHttp.Requests as well as the simplicity and robustness that comes with it. Read more about these benefits
in this article introducing StaticHttp requests and some concepts around it.
The full details to perform a StaticHttp request.
A simplified helper around StaticHttp.request, which builds up a StaticHttp GET request.
import Json.Decode as Decode exposing (Decoder)
import Pages.StaticHttp as StaticHttp
getRequest : StaticHttp.Request Int
getRequest =
StaticHttp.get
(Secrets.succeed "https://api.github.com/repos/dillonkearns/elm-pages")
(Decode.field "stargazers_count" Decode.int)Build a StaticHttp request (analagous to Http.request).
This function takes in all the details to build a StaticHttp request, but you can build your own simplified helper functions
with this as a low-level detail, or you can use functions like StaticHttp.get.
Transform a request into an arbitrary value. The same underlying HTTP requests will be performed during the build step, but mapping allows you to change the resulting values by applying functions to the results.
A common use for this is to map your data into your elm-pages view:
import Json.Decode as Decode exposing (Decoder)
import Pages.StaticHttp as StaticHttp
view =
StaticHttp.get
(Secrets.succeed "https://api.github.com/repos/dillonkearns/elm-pages")
(Decode.field "stargazers_count" Decode.int)
|> StaticHttp.map
(\stars ->
{ view =
\model viewForPage ->
{ title = "Current stars: " ++ String.fromInt stars
, body = Html.text <| "⭐️ " ++ String.fromInt stars
, head = []
}
}
)This is useful for prototyping with some hardcoded data, or for having a view that doesn't have any StaticHttp data.
import Pages.StaticHttp as StaticHttp
view :
List ( PagePath Pages.PathKey, Metadata )
->
{ path : PagePath Pages.PathKey
, frontmatter : Metadata
}
->
StaticHttp.Request
{ view : Model -> View -> { title : String, body : Html Msg }
, head : List (Head.Tag Pages.PathKey)
}
view siteMetadata page =
StaticHttp.succeed
{ view =
\model viewForPage ->
mainView model viewForPage
, head = head page.frontmatter
}Stop the StaticHttp chain with the given error message. If you reach a fail in your request,
you will get a build error. Or in the dev server, you will see the error message in an overlay in your browser (and in
the terminal).
The way you build a body is analagous 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!
A body for a StaticHttp request.
Build an empty body for a StaticHttp request. See elm/http's Http.emptyBody.
Builds a string body for a StaticHttp 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!
Builds a JSON body for a StaticHttp request. See elm/http's Http.jsonBody.
Build off of the response from a previous StaticHttp request to build a follow-up request. You can use the data
from the previous response to build up the URL, headers, etc. that you send to the subsequent request.
import Json.Decode as Decode exposing (Decoder)
import Pages.StaticHttp as StaticHttp
licenseData : StaticHttp.Request String
licenseData =
StaticHttp.get
(Secrets.succeed "https://api.github.com/repos/dillonkearns/elm-pages")
(Decode.at [ "license", "url" ] Decode.string)
|> StaticHttp.andThen
(\licenseUrl ->
StaticHttp.get (Secrets.succeed licenseUrl) (Decode.field "description" Decode.string)
)Helper to remove an inner layer of Request wrapping.
Turn a list of StaticHttp.Requests into a single one.
import Json.Decode as Decode exposing (Decoder)
import Pages.StaticHttp as StaticHttp
type alias Pokemon =
{ name : String
, sprite : String
}
pokemonDetailRequest : StaticHttp.Request (List Pokemon)
pokemonDetailRequest =
StaticHttp.get
(Secrets.succeed "https://pokeapi.co/api/v2/pokemon/?limit=3")
(Decode.field "results"
(Decode.list
(Decode.map2 Tuple.pair
(Decode.field "name" Decode.string)
(Decode.field "url" Decode.string)
|> Decode.map
(\( name, url ) ->
StaticHttp.get (Secrets.succeed url)
(Decode.at
[ "sprites", "front_default" ]
Decode.string
|> Decode.map (Pokemon name)
)
)
)
)
)
|> StaticHttp.andThen StaticHttp.combineLike map, but it takes in two Requests.
view siteMetadata page =
StaticHttp.map2
(\elmPagesStars elmMarkdownStars ->
{ view =
\model viewForPage ->
{ title = "Repo Stargazers"
, body = starsView elmPagesStars elmMarkdownStars
}
, head = head elmPagesStars elmMarkdownStars
}
)
(get
(Secrets.succeed "https://api.github.com/repos/dillonkearns/elm-pages")
(Decode.field "stargazers_count" Decode.int)
)
(get
(Secrets.succeed "https://api.github.com/repos/dillonkearns/elm-markdown")
(Decode.field "stargazers_count" Decode.int)
)Warning - use these at your own risk! It's highly recommended that you use the other request functions that make use of
zwilias/json-decode-exploration in order to allow you to reduce down your JSON to only the values that are used by
your decoders. This can significantly reduce download sizes for your StaticHttp requests.
This is an alternative to the other request functions in this module that doesn't perform any optimizations on the
asset. Be sure to use the optimized versions, like StaticHttp.request, if you can. Using those can significantly reduce
your asset sizes by removing all unused fields from your JSON.
You may want to use this function instead if you need XML data or plaintext. Or maybe you're hitting a GraphQL API, so you don't need any additional optimization as the payload is already reduced down to exactly what you requested.
Analgous to the Expect type in the elm/http package. This represents how you will process the data that comes
back in your StaticHttp request.
You can derive ExpectUnoptimizedJson 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.
Request a raw String. You can validate the String if you need to check the formatting, or try to parse it
in something besides JSON. Be sure to use the StaticHttp.request function if you want an optimized request that
strips out unused JSON to optimize your asset size.
If the function you pass to expectString yields an Err, then you will get at StaticHttpDecodingError that will
fail your elm-pages build and print out the String from the Err.
request =
StaticHttp.unoptimizedRequest
(Secrets.succeed
{ url = "https://example.com/file.txt"
, method = "GET"
, headers = []
, body = StaticHttp.emptyBody
}
)
(StaticHttp.expectString
(\string ->
if String.toUpper string == string then
Ok string
else
Err "String was not uppercased"
)
)Handle the incoming response as JSON and don't optimize the asset and strip out unused values.
Be sure to use the StaticHttp.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 at StaticHttpDecodingError that will
fail your elm-pages build and print out the String from the Err.
A Request that will be made a build time. Multiple
StaticHttp.Requests can be combined together using themapNfunctions, very similar to how you can manipulate values with Json Decoders in Elm.