• Stars
    star
    20
  • Rank 1,121,974 (Top 23 %)
  • Language
    Crystal
  • License
    MIT License
  • Created about 6 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

The HTTP params parsing module for Crystal πŸ€“

HTTP::Params::Serializable

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

The HTTP params serialization module for Crystal.

Supporters

Thanks to all my patrons, I can build and support beautiful Open Source Software! πŸ™

Lauri Jutila, Alexander Maslov, Dainel Vera

You can become a patron too in exchange of prioritized support and other perks

Become Patron

About

This module is intended to provide a simple and convenient way to make an object to safely initialize from an HTTP params query (be it an URL query or "application/x-www-form-urlencoded" body). It tries to have an API almost the same as existing JSON::Serializable and YAML::Serializable modules, thus allowing to serialize infinitely-nested structures, including Arrays and Hashes.

Installation

  1. Add the dependency to your shard.yml:
dependencies:
  http-params-serializable:
    github: vladfaust/http-params-serializable
    version: ~> 0.4.0
  1. Run shards install

Usage

Simple example:

require "http-params-serializable"

struct Params
  include HTTP::Params::Serializable
  getter id : Int32
end

params = Params.from_query("id=42")
pp params.id.class # => Int32
pp params.to_query # => "id=42"

Params.from_query("")
# HTTP::Params::Serializable::ParamMissingError: Parameter "id" is missing

Params.from_query("id=foo")
# HTTP::Params::Serializable::ParamTypeCastError: Parameter "id" cannot be cast from "foo" to Int32

As you may expect, unions work as well:

struct Params
  include HTTP::Params::Serializable
  getter id : Int32 | Nil
end

params = Params.from_query("id=")
pp params.id # => nil

Arrays are supported too:

struct Params
  include HTTP::Params::Serializable
  getter foo : Array(Float32)
end

params = Params.from_query("foo[]=42.0&foo[]=43.5")
pp params.foo[1] # => 43.5
pp params.to_query # => "foo[]=42.0&foo[]=43.5"

Nested params are supported:

struct Params
  include HTTP::Params::Serializable
  getter nested : Nested

  struct Nested
    include HTTP::Params::Serializable
    getter foo : Bool
  end
end

params = Params.from_query("nested[foo]=true")
pp params.nested.foo # => true
pp params.to_query # => "nested[foo]=true"

Nested arrays are supported as well:

struct Params
  include HTTP::Params::Serializable
  getter nested : Array(Nested)

  struct Nested
    include HTTP::Params::Serializable
    getter foo : Array(Int32)
  end
end

params = Params.from_query("nested[0][foo][]=1&nested[0][foo][]=2")
pp params.nested.first.foo.first # => [1, 2]
pp params.to_query # ditto

It is also possible to alter the serialization behaviour with @[HTTP::Param] annotation. It currently supports two options: :key and :converter. Read more in docs.

struct Params
  include HTTP::Params::Serializable

  @[HTTP::Param(key: "the___Time", converter: Time::EpochConverter)]
  getter time : Time
end

params = Params.from_query("the___Time=1544958806")
pp params.time # => 2018-12-16 11:13:26.0 UTC
pp params.to_query # => "the___Time=1544958806"

Custom serialization rules

If you want to know-how to make custom objects serializable, read the Custom serialization rules Wiki page.

Usage with Onyx::REST

Onyx::REST comes with an Action module, which implements common param sources parsing, which uses this shard under the hood:

require "onyx/rest"

struct UpdateUser
  include Onyx::REST::Action

  params do
    # Path params ("/users/:id")
    path do
      type id : Int32
    end

    # Query params ("/users/42?password=secret")
    # Nesting and arrays natively supported
    query do
      type password : String
      type foo do
        type bar : Int32?
      end
    end

    # Full support for form-data payloads
    form do
      type username : String?
      type email : String?
    end
  end

  errors do
    type Forbidden(403)
  end

  def call
    user = Onyx.query(User.where(id: params.path.id))
    raise Forbidden.new unless user.password == params.query.password
  end
end

Onyx.put "/users/:id", UpdateUser
Onyx.listen

Usage with Kemal

It's pretty simple to make your Kemal applications more safe:

require "kemal"
require "http-params-serializable"

struct Params
  include HTTP::Params::Serializable
  getter id : Int32
end

get "/" do |env|
  if query = env.request.query
    query_params = Params.from_query(query)

    if query_params.id > 0
      "#{query_params.id} is positive\n"
    else
      "#{query_params.id} is negative or zero\n"
    end
  else
    "Empty query\n"
  end
rescue ex : HTTP::Params::Serializable::Error
  ex.message.not_nil! + "\n"
end

Kemal.run
$ curl http://localhost:3000?id=42
42 is positive
$ curl http://localhost:3000?id=-1
-1 is negative or zero
$ curl http://localhost:3000?id=foo
Parameter "id" cannot be cast from "foo" to Int32

Development

crystal spec and you're good to go.

Contributing

  1. Fork it (https://github.com/vladfaust/http-params-serializable/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

More Repositories

1

unity-wakatime

WakaTime plugin for Unity ⏱
C#
116
star
2

crystalworld

RealWorld back-end API implementation πŸ‘
Crystal
43
star
3

migrate.cr

A database migration solution 🚜
Crystal
31
star
4

i18n.cr

Internationalization shard 🌍
Crystal
24
star
5

jbuilder-json_api

Jbuilder meets jsonapi.org specifications
Ruby
23
star
6

http-multiserver.cr

Mount multiple web applications 🚦
Crystal
23
star
7

tarantool.cr

The Tarantool driver (a.k.a. connector) πŸ•·
Crystal
19
star
8

mini_redis

A light-weight low-level Redis client for Crystal ♨️
Crystal
18
star
9

validations.cr

Validations module for Crystal βœ…
Crystal
13
star
10

tele.cr

A convenient Telegram Bot framework πŸ€–
Crystal
13
star
11

callbacks.cr

Expressive callbacks module for Crystal πŸš‰
Crystal
12
star
12

background

Fast background job processing
Crystal
11
star
13

stripe.cr

🚧 WIP 🚧 Stripe API wrapper πŸ’³
Crystal
7
star
14

onyx-http-deprecated

Deprecated Onyx module
Crystal
6
star
15

cake-bake

Bake Cakefile into native Crystal code 🍞
Crystal
5
star
16

time-span-humanize

Time::Span#humanize method
Crystal
5
star
17

crack

Alternative Crystal HTTP server implementation
Crystal
5
star
18

timer.cr

A versatile timer module ⏲
Crystal
4
star
19

realworld-benchmark

RealWorld Benchmark
Crystal
3
star
20

onyx-40-loc-distributed-chat

Distributed websocket chat in 40 lines of code
JavaScript
2
star
21

time_format.cr

Time spans formatting made simple ⌚️
Crystal
2
star
22

Expense-Manager-2

Java
1
star
23

tele-broadcast.cr

Broadcasting for Tele πŸ“’
Crystal
1
star
24

attribute_enum

Rails-like enums with ease
Ruby
1
star