Skip to content

Commit

Permalink
Merge pull request #131 from mamantoha/params-encoders
Browse files Browse the repository at this point in the history
Params encoders
  • Loading branch information
mamantoha authored Mar 13, 2020
2 parents d551715 + b799055 commit 622d7b3
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 154 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [...]

* Add `Crest#ParamsEncoder` module to encode/decode URI querystring
* Replace `Crest::Utils#encode_query_string` `with Crest::ParamsEncoder#encode`
* Allow `Boolean` in params

## [0.23.2][] (2020-01-03)

* Fix an issue with wrong "Content-Type" header
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,28 @@ end

This section covers some of `crest` more advanced features.

#### Parameters serializer

Under the hood `crest` uses `Crest::ParamsEncoder` module to encode param.

The encoder affect both how `crest` processes query strings and how it serializes POST bodies.

`Crest::ParamsEncoder` provides 2 methods:

* `#encode` - converts the given param into a URI querystring

```crystal
Crest::Params.encode({"a" => ["one", "two", "three"], "b" => true, "c" => "C", "d" => 1})
# => 'a[]=one&a[]=two&a[]=three&b=true&c=C&d=1'
```

* `#decode` - converts the given URI querystring into a hash

```crystal
Crest::Params.decode("a[]=one&a[]=two&a[]=three&b=true&c=C&d=1")
# => {"a" => ["one", "two", "three"], "b" => "true", "c" => "C", "d" => "1"}
```

#### Multipart

Yeah, that's right! This does multipart sends for you!
Expand Down
4 changes: 2 additions & 2 deletions shard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ authors:
- Anton Maminov <anton.maminov@gmail.com>

description: |
Simple HTTP and REST client for Crystal, inspired by the Ruby's RestClient gem.
HTTP and REST client for Crystal
crystal: 0.32.0
crystal: 0.33.0

dependencies:
http-client-digest_auth:
Expand Down
138 changes: 138 additions & 0 deletions spec/unit/params_encoder_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
require "../spec_helper"

describe Crest::ParamsEncoder do
describe "#encode" do
it "encodes hash" do
input = {:foo => "123", :bar => "456"}
output = "foo=123&bar=456"

Crest::ParamsEncoder.encode(input).should eq(output)
end

it "encodes hash as http url-encoded" do
input = {:email => "user@example.com", :title => "Hello world!"}
output = "email=user%40example.com&title=Hello+world%21"

Crest::ParamsEncoder.encode(input).should eq(output)
end

it "encodes hash with nil" do
input = {:foo => nil, :bar => "2"}
output = "foo=&bar=2"

Crest::ParamsEncoder.encode(input).should eq(output)
end

it "encodes hash with boolean" do
input = {:foo => true, :bar => "2"}
output = "foo=true&bar=2"

Crest::ParamsEncoder.encode(input).should eq(output)
end

it "encodes hash with symbol" do
input = {:foo => :bar}
output = "foo=bar"

Crest::ParamsEncoder.encode(input).should eq(output)
end

it "encodes hash with numeric values" do
input = {:foo => 1, :bar => 2}
output = "foo=1&bar=2"

Crest::ParamsEncoder.encode(input).should eq(output)
end

it "encodes complex objects" do
input = {"a" => ["one", "two", "three"], "b" => true, "c" => "C", "d" => 1}
output = "a%5B%5D=one&a%5B%5D=two&a%5B%5D=three&b=true&c=C&d=1"

Crest::ParamsEncoder.encode(input).should eq(output)
end
end

describe "#decode" do
it "decodes simple params" do
query = "foo=1&bar=2"
params = {"foo" => "1", "bar" => "2"}

Crest::ParamsEncoder.decode(query).should eq(params)
end

it "decodes params with nil" do
query = "foo=&bar=2"
params = {"foo" => nil, "bar" => "2"}

Crest::ParamsEncoder.decode(query).should eq(params)
end

it "decodes array " do
query = "a[]=one&a[]=two&a[]=three"
params = {"a" => ["one", "two", "three"]}

Crest::ParamsEncoder.decode(query).should eq(params)
end

it "decodes hashes" do
query = "user[login]=admin"
params = {"user" => {"login" => "admin"}}

Crest::ParamsEncoder.decode(query).should eq(params)
end

it "decodes escaped string" do
query = "user%5Blogin%5D=admin"
params = {"user" => {"login" => "admin"}}

Crest::ParamsEncoder.decode(query).should eq(params)
end
end

describe "#flatten_params" do
it "transform nested param" do
input = {:key1 => {:key2 => "123"}}
output = [{"key1[key2]", "123"}]

Crest::ParamsEncoder.flatten_params(input).should eq(output)
end

it "transform deeply nested param" do
input = {:key1 => {:key2 => {:key3 => "123"}}}
output = [{"key1[key2][key3]", "123"}]

Crest::ParamsEncoder.flatten_params(input).should eq(output)
end

it "transform deeply nested param with file" do
file = File.open("#{__DIR__}/../support/fff.png")
input = {:key1 => {:key2 => {:key3 => file}}}
output = [{"key1[key2][key3]", file}]

Crest::ParamsEncoder.flatten_params(input).should eq(output)
end

it "transform nested param with array" do
input = {:key1 => {:arr => ["1", "2", "3"]}, :key2 => "123"}
output = [{"key1[arr][]", "1"}, {"key1[arr][]", "2"}, {"key1[arr][]", "3"}, {"key2", "123"}]

Crest::ParamsEncoder.flatten_params(input).should eq(output)
end

it "parse nested params with files" do
file = File.open("#{__DIR__}/../support/fff.png")

input = {:key1 => {:key2 => file}}
output = [{"key1[key2]", file}]

Crest::ParamsEncoder.flatten_params(input).should eq(output)
end

it "parse simple params with nil value" do
input = {:key1 => nil}
output = [{"key1", nil}]

Crest::ParamsEncoder.flatten_params(input).should eq(output)
end
end
end
87 changes: 0 additions & 87 deletions spec/unit/utils_spec.cr

This file was deleted.

2 changes: 1 addition & 1 deletion src/crest.cr
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ require "./http/proxy/client"
module Crest
VERSION = {{ `shards version #{__DIR__}`.chomp.stringify }}

alias TextValue = String | Symbol | Int32 | Nil
alias TextValue = String | Symbol | Int32 | Bool | Nil

alias Params = Hash(Symbol | String, Int32 | String) |
Hash(String, String | Int32) |
Expand Down
2 changes: 1 addition & 1 deletion src/crest/forms/data_form.cr
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module Crest
end

def parsed_params
Crest::Utils.flatten_params(@params)
Crest::ParamsEncoder.flatten_params(@params)
end

private def add_field(formdata : HTTP::FormData::Builder, name : String | Symbol, value : TextValue)
Expand Down
2 changes: 1 addition & 1 deletion src/crest/forms/urlencoded_form.cr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module Crest
end

def parsed_params
Crest::Utils.encode_query_string(@params)
Crest::ParamsEncoder.encode(@params)
end
end
end
Loading

0 comments on commit 622d7b3

Please sign in to comment.