The HTTP params parsing module for Crystal 🤓
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
spec
src
.editorconfig
.gitignore
.travis.yml
LICENSE
README.md
shard.yml

README.md

⚠️ This shard requires Crystal master to compile. See installation instructions for Crystal.

Params

Built with Crystal Build status Docs Releases Awesome vladfaust.com Patrons count

The HTTP params parsing module for Crysal.

Become Patron

About

This module adds Params.mapping method to the top-level namespace which turns an Object into a type-safe params container. An initialize(HTTP::Request) method will be added to it, which would parse params from these sources in this particular order, overwriting if needed:

  • Resource params from request.resource_params or .uri_params or .path_params (should be set externally, e.g. by a router)
  • HTTP query params (e.g. "/?id=42")
  • Body depending on "Content-Type" header, currently supporting "application/x-www-form-urlencoded", "multipart/form-data" and "application/json"

The params object will have getters defined as in the mapping, e.g. .id.

Installation

Add this to your application's shard.yml:

dependencies:
  params:
    github: vladfaust/params.cr
    version: ~> 0.1.2

This shard follows Semantic Versioning v2.0.0, so check releases and change the version accordingly.

Usage

Call Params.mapping from within an object to turn it into a params container. The object would have got getters defined in accordance with the mapping, i.e. id, name and additional_data in the following example:

require "params"

struct MyParams
  Params.mapping({
    id:   Int32,
    name: String?, # Nilable params

    # Nesting is supported
    # "under_score", "CamelCase", "lowerCamelCase" and "kebab-case"
    # are considered valid upon parsing, however, you should use "under_score"
    # casing in the mapping itself (i.e. in this code).
    #
    # Therefore, "additional_data", "AdditionalData", "additionalData" and "additional-data" is OK
    additional_data: {
      email: String,
      bio:       String | Nil,  # Alternative syntax for nilable params
      tags:      Array(String), # Arrays are supported too

      # Nesting is possible with ∞ levels
      deep: {
        random_numbers: Array(UInt64) | Nil, # Nilable arrays

        admin:   Bool,
        balance: Union(Float64 | Null), # Explicit `null` differs from `nil`
      } | Nil, # Nilable nesting
    },
  })
end

params = MyParams.new(context.request) # Initialize it with a HTTP::Request,
                                       # this would trigger the parsing

params.id                    # => 42
params.name                  # => "John"
params.additional_data.email # => user@example.com

The following is an example of a valid HTTP query for this params object, formatted for convenience. You may note that keys are case-insensitive. This structure also applies for "application/x-www-form-urlencoded" and "multipart/form-data" content types:

https://example.com/path?id=42
&name=Jake
&additionalData[email]=foo@example.com
&AdditionalData[bio]=foo
&additional_data[tags][]=a
&additional-data[tags]=b
&additionalData[deep][randomNumbers][]=1
&AdditionalData[deep][RandomNumbers][]=2
&additional_data[deep][admin]=true
&additional-data[deep][balance]=42000.42

An example of a valid JSON body would be:

{
  "id": 42,
  "name": "John",
  "additionalData": {
    "email": "foo@example.com",
    "bio": "foo",
    "tags": ["foo", "bar"],
    "deep": {
      "randomNumbers": [1, 2],
      "admin": true,
      "balance": null
    }
  }
}

Parsing may eventually raise Params::TypeCastError if an incoming parameter cannot be casted into desired type, or Params::MissingError when a required (i.e. non-nilable) parameter is missing. There is a bunch of other possible errors, see the docs.

Development

crystal spec and you're good to go.

Contributing

  1. Fork it (https://github.com/vladfaust/params.cr/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors