Skip to content

Commit

Permalink
feat: add support for third-party request libs
Browse files Browse the repository at this point in the history
  • Loading branch information
kimburgess committed Jun 4, 2020
1 parent 920dec1 commit ba89afc
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 14 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ In the wise words of the modern poet Ice Cube:
Responsible is a library that makes it simple, fast an easy to check HTTP responses in crystal-lang.
It provides a lightweight API for dealing with errors, logging and static, type-safe parsing.
It works directly with `HTTP::Client::Response` objects and can function in tandem with clients that build on top of these.
Third party libraries (like [halite](https://github.com/icyleaf/halitea), [crest](https://github.com/mamantoha/crest) and others) are [supported](#third-party-support) too!


## What this isn't
Expand Down Expand Up @@ -149,6 +150,21 @@ To return `nil` in case of a parser error, use:
response.parse_to?(MaybeMyType)
```

## Third-party support

Responsible works around a [minimal response object interface](./src/responsible/response_interface.cr).
When you `require "responsible"`, support loads for `HTTP::Client::Response` objects by default.
To support third party response objects use the `Responsible.support` macro.
```crystal
require "Halite"
Responsible.support Halite::Response
response = ~Halite.get("https://www.example.com") >> NamedTuple(message: String)
response[:message]
```


## Contributors

- [Kim Burgess](https://github.com/KimBurgess) - creator and maintainer
8 changes: 0 additions & 8 deletions src/core_ext/http/client/response.cr

This file was deleted.

10 changes: 9 additions & 1 deletion src/responsible.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require "./responsible/**"
require "./core_ext/**"
require "http/client/response"

module Responsible
HANDLERS = {} of ResponseType => Action
Expand All @@ -10,4 +10,12 @@ module Responsible
HANDLERS[ResponseType::{{type}}] = block
end
{% end %}

macro support(response_type)
class {{response_type.id}}
include Responsible::ResponseInterface
end
end
end

Responsible.support HTTP::Client::Response
12 changes: 7 additions & 5 deletions src/responsible/response.cr
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
require "http/client/response"
require "json"
require "./response_interface"
require "./response_type"

class Responsible::Response
@response : HTTP::Client::Response
@response : ResponseInterface
@type : ResponseType
@in_handler : Bool = false

Expand Down Expand Up @@ -48,10 +48,12 @@ class Responsible::Response
def parse_to(x : T.class, ignore_response_code = @in_handler, &block : Exception -> U) : T | U forall T, U
raise Error.from(self) unless success? || ignore_response_code

case headers["content-type"]
when .starts_with? "application/json"
content_type = headers["content-type"].split(' ').first.downcase

case content_type
when "application/json"
begin
T.from_json(body || body_io)
T.from_json(@response.body? || @response.body_io)
rescue e
yield e
end
Expand Down
18 changes: 18 additions & 0 deletions src/responsible/response_interface.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require "http/status"
require "http/headers"
require "./response"

module Responsible::ResponseInterface
abstract def status : HTTP::Status

abstract def headers : HTTP::Headers

abstract def body? : String?

abstract def body_io : IO

# Wraps `self` into a `Responsible::Response`.
def ~
Responsible::Response.new(self)
end
end

0 comments on commit ba89afc

Please sign in to comment.