Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion elm.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
"dependencies": {
"FabienHenon/jsonapi": "2.0.2 <= v < 3.0.0",
"elm/core": "1.0.2 <= v < 2.0.0",
"elm/file": "1.0.5 <= v < 2.0.0",
"elm/http": "2.0.0 <= v < 3.0.0",
"elm/json": "1.1.3 <= v < 2.0.0",
"krisajenkins/remotedata": "6.0.1 <= v < 7.0.0"
},
"test-dependencies": {}
}
}
79 changes: 79 additions & 0 deletions src/Http/Request.elm
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Http.Request exposing
( Request, RequestCustomData, RequestNoContent
, request, requestCustomData, requestNoContent
, RequestFiles, requestFiles
)

{-| `Http.Request` allows you to create http requests with [`jsonapi`](https://package.elm-lang.org/packages/FabienHenon/jsonapi/latest/) objects.
Expand All @@ -20,6 +21,7 @@ The `content-type` used in the request headers is `application/vnd.api+json` acc

-}

import File exposing (File)
import Http
import Http.Error exposing (RequestError(..))
import Http.Methods
Expand Down Expand Up @@ -55,6 +57,21 @@ type alias RequestCustomData data =
}


{-| Defines a `Request` with a url, some headers, a list of files, and a custom decoder.
`data` is the type of the object you would like to decode.
-}
type alias RequestFiles meta data msg =
{ url : Http.Url.Url
, headers : List Http.Header
, multipartNames : List String
, files : List File
, multipartEncoder : String -> File -> Http.Part
, documentDecoder : JD.Decoder (Result (List Decode.Error) (Document meta data))
, tracker : Maybe String
, msg : RemoteData.RemoteData RequestError (Document meta data) -> msg
}


{-| Defines a `Request` with a url, some headers, and a body. There is no content decoder.
Useful for `DELETE` requests for instance.
-}
Expand Down Expand Up @@ -97,6 +114,23 @@ requestCustomData request_ =
}


{-| Create a request files that will decode a jsonapi object
-}
requestFiles : RequestFiles meta data msg -> Cmd msg
requestFiles request_ =
Http.request
{ method = request_.url |> .method |> Http.Methods.toString
, headers =
Http.header "Accept" "application/vnd.api+json"
:: request_.headers
, url = request_.url |> .url
, body = List.map2 request_.multipartEncoder request_.multipartNames request_.files |> Http.multipartBody
, expect = resourceExpecter request_.msg request_.documentDecoder
, timeout = Nothing
, tracker = request_.tracker
}


{-| Create a request task that will expect nothing to decode
-}
requestNoContent : RequestNoContent -> Task Never (RemoteData.RemoteData RequestError ())
Expand All @@ -113,6 +147,51 @@ requestNoContent request_ =
}


resourceExpecter : (RemoteData.RemoteData RequestError (Document meta data) -> msg) -> JD.Decoder (Result (List Decode.Error) (Document meta data)) -> Http.Expect msg
resourceExpecter msg documentDecoder =
Http.expectStringResponse (Result.withDefault (RemoteData.Failure (CustomError "Unknown error")) >> msg) <|
\response ->
case response of
Http.BadUrl_ url ->
Ok (RemoteData.Failure (HttpError (Http.BadUrl url)))

Http.Timeout_ ->
Ok (RemoteData.Failure (HttpError Http.Timeout))

Http.NetworkError_ ->
Ok (RemoteData.Failure (HttpError Http.NetworkError))

Http.BadStatus_ metadata body ->
if metadata.statusCode == 422 then
case JD.decodeString documentDecoder body of
Ok document ->
case document of
Err errors ->
Ok (RemoteData.Failure (JsonApiError errors))

Ok doc ->
Ok (RemoteData.Success doc)

Err err ->
Ok (RemoteData.Failure (HttpError (Http.BadBody (JD.errorToString err))))

else
Ok (RemoteData.Failure (HttpError (Http.BadStatus metadata.statusCode)))

Http.GoodStatus_ metadata body ->
case JD.decodeString documentDecoder body of
Ok document ->
case document of
Err errors ->
Ok (RemoteData.Failure (JsonApiError errors))

Ok doc ->
Ok (RemoteData.Success doc)

Err err ->
Ok (RemoteData.Failure (HttpError (Http.BadBody (JD.errorToString err))))


resourceResolver : JD.Decoder (Result (List Decode.Error) a) -> Http.Resolver Never (RemoteData.RemoteData RequestError a)
resourceResolver documentDecoder =
Http.stringResolver <|
Expand Down