Giter Club home page Giter Club logo

Comments (16)

adamluzsi avatar adamluzsi commented on May 20, 2024

Hello @janfri !
You are right , right now the wasn't user stories to start the validate_payload epic and because this , this functionality only have mindmap and a basic sketch level implementation for spiking , but nothing released at this point.

We thinking about the following singleton method

.payload do
  unserialize do
    on "request content type here" do |payload|
       CustomUnserialize.parse(payload)
    end
    on "application/json" do |payload|
       JSON.parse(payload)
    end
  end

  validate do
    it_is_a Array, of: Hash do |element|
      element.has_a_key "foo", which_is_a: String
    end
  end

end
get "/baz" do
  payload #> [{"Foo" => "bar"}]
end

But it's an early concept, and we still in the process gathering user stories from our production use cases .

It would be great if you could provide example scenarios to us if you don't mind the time :)))

from rack-app.

janfri avatar janfri commented on May 20, 2024

Payload may be complex so it could become epic indeed. ;-)

My current case is a very simple API in REST style. I need only one simple param message of type string with size between 1 and 30.

My current solution is something like:

require 'rack/app'
require 'json'

class App < Rack::App

  def form_data
    case request.media_type
    when 'application/json'
      request.body.rewind
      JSON.parse(request.body.read)
    else
      request.POST
    end
  end

  def size_in_range? obj, range
    (obj.respond_to? :size) && (range === obj.size)
  end

  desc 'create a new event'
  post '/events' do
    msg = form_data['message']
    if size_in_range? msg, 1..30
      # create event
      'New event created'
    else
      # do error handling
      response.status = 400
      'no valid message given'
    end
  end

end

run App

So I can send the data URL-encoded, FORM-DATA-encoded or JSON-encoded:

$ curl -X POST -d message=foo http://localhost:9292/events
New event created
$ curl -X POST -F message=foo http://localhost:9292/events
New event created
$ curl -H "Content-Type: application/json" -X POST -d '{"message": "foo"}' http://localhost:9292/events
New event created

from rack-app.

adamluzsi avatar adamluzsi commented on May 20, 2024

Awesome ! I think we should provide something that doesn't include custom dsl but something that is easy to understand and generic.

I start working on your request, as soon as the formats epic gets done. :)

from rack-app.

adamluzsi avatar adamluzsi commented on May 20, 2024

okey, all the stuff from the team backlog went out,
today after work I start to work on your request @janfri : )))))

from rack-app.

janfri avatar janfri commented on May 20, 2024

Great news. :-)

from rack-app.

adamluzsi avatar adamluzsi commented on May 20, 2024

I split up your epic into two part.

one for the payload parsing based on content_type,
and one for the validating the parsed payload with a middleware.

For the first, what do you think, should it be go under the "payload" and "payload_stream" method as a dynamic object that is behave based on the content type unserialization, or there should be a new method, something like "parsed_payload" and "parsed_payload_stream" ?

from rack-app.

janfri avatar janfri commented on May 20, 2024

@adamluzsi

split up your epic into two part.

one for the payload parsing based on content_type,
and one for the validating the parsed payload with a middleware.

Sounds reasonable.

For the first, what do you think, should it be go under the "payload" and "payload_stream" method as a dynamic object that is behave based on the content type unserialization, or there should be a new method, something like "parsed_payload" and "parsed_payload_stream" ?

Maybe both?

  • For simple cases methods like parsed_payload or parsed_payload_stream would be comfortable. Examples are simple deserializers for JSON and XML.
  • For "strange" things maybe an IO object would be useful? (I'm not sure!) A use case could be to "parse" an uploded media file with mini_exiftool to get meta data for further work with the file.

Just my 2 cents. Maybe others have better ideas?

from rack-app.

adamluzsi avatar adamluzsi commented on May 20, 2024

I talked about this with @BlasiusVonSzerencsi who use actively in production, and he mentioned, that it would be awesome if the :payload method would be dynamic based on the content_type, and there would be a :raw_payload for those, who want work explicitly with the string content of the payload.

from rack-app.

janfri avatar janfri commented on May 20, 2024

the :payload method would be dynamic based on the content_type, and there would be a :raw_payload for those, who want work explicitly with the string content of the payload.

Accepted.

What should be the reaction to a request with an unsupported content_type? Should there be an automatic HTTP 415 response? Or should payload then have the unparsed content?

from rack-app.

adamluzsi avatar adamluzsi commented on May 20, 2024

The default behavior is the raw string .
So the already made specs won't break.
Anything that make pre requirement should go to validate_payload block , so it can be processed into documentation as well.
The payload method it self should not do any validation , and only serve as a data input in the controller.

That's the current direction if you like it. :)))

I already started to design the validate_payload method that almost alike with the validated_params syntax.

from rack-app.

adamluzsi avatar adamluzsi commented on May 20, 2024

Hello @janfri, sorry for not taking care of your issue, my daughter born and life was busy with this in these days. <3

I soon start to work on your request as soon as I can.

Best regards
Adam L.

from rack-app.

janfri avatar janfri commented on May 20, 2024

I'll be patient. ;-)

from rack-app.

adamluzsi avatar adamluzsi commented on May 20, 2024

You are such an amazing person, thank you very much! :)

from rack-app.

adamluzsi avatar adamluzsi commented on May 20, 2024

Hy @janfri !

Update in the implementation. Yesterday, I talked about your feature request with my friends, and they suggested, that I should implement this as a middleware (which was in the original plan to).
The Payload now is configurable, and you can tell to accept one or more input format.
In this way, we don't break the rolling release backward compatibility, while the developers have a bigger range of control over what and how can be used in the application.
This also means, that the payload/parser block is optional for those who require and not forced to others.

Any opinion?

require 'rack/app'
class App < Rack::App

  payload do
    parser do

      accept :json, :www_form_urlencoded

      on "x-custom-content-type" do |io|
        MyCustomContentTypeParser.load(io)
      end 
      
    end
  end

  desc 'health check endpoint'
  get '/' do
    payload #> is an object based on the content type and the defined custom parsers
  end

end

from rack-app.

adamluzsi avatar adamluzsi commented on May 20, 2024
rack-app 5.7.0 built to pkg/rack-app-5.7.0.gem.
Tagged v5.7.0.
Pushed git commits and tags.
Pushed rack-app 5.7.0 to rubygems.org.

from rack-app.

adamluzsi avatar adamluzsi commented on May 20, 2024

I Still think about the Validation. Is it really required ?
I Can't find any use case to drive this part now.

For Example, all the use case I found, were using a custom Error handler block + a class that validate the payload based on restful params.
And it is kind of idiomatic from the Rack and the middleware use mechanism.

class App < Rack::App 
  
  get "/" do
    CustomValidation.new(payload)
    payload
  end

  error CustomValidationError do |ex| 
    response.status = 400 
    response.write(ex.message)
    finish!
  end 

end 
    

from rack-app.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.