GithubHelp home page GithubHelp logo

crystal-community / cossack Goto Github PK

View Code? Open in Web Editor NEW
105.0 105.0 11.0 416 KB

Simple and flexible HTTP client for Crystal with middleware and test support.

License: GNU Lesser General Public License v3.0

Crystal 98.67% Makefile 1.33%
crystal middleware

cossack's People

Contributors

aisrael avatar benoist avatar greyblake avatar thelonelyghost avatar veelenga avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

cossack's Issues

Allow specifying middleware "globally"

Hi! Is there a way to specify Cossack Middleware to inject to every Cossack client?

Use cases:

  1. Specify Proxy Middleware (when it's implemented) once at application startup
  2. Potentially create a VCR-like middleware that can be specified at spec_helper.cr

Add possibility to turn-off server certificate validation

When dealing with intranet resources - it is very annoying for OS administrators to push internal CA certificates as "trusted" to all clients. Our administrators not too lazy, but they cant do this properly too.
It will be nice if cossack will provide some parameter like ssl_params, which can be used to turn-off server SSL certificate validation.
Thank you!

undefined method 'new' for Cossack:Module

crystal version: Crystal 0.17.4 (2016-05-26)

shards.yml:

dependencies:
  cossack:
    github: greyblake/crystal-cossack

cr file:

require "cossack"
cossack = Cossack.new

simple get requests don't follow redirects

Hi -
I'm having a bit of trouble using the simple get example listed.

response = Cossack.get("http://doomy.tumblr.com/api/read/json")

returns a status of 301.

However, this works correctly.

cossack = Cossack::Client.new do |client|
  # follow up to 10 redirections (by default 5)
  client.use Cossack::RedirectionMiddleware, limit: 10
end

return cossack.get("http://doomy.tumblr.com/api/read/json")

Is this intended? I would like to use the simple Cossack.get static method as I don't need to configure anything, however it gives me a 301 instead of following the redirect.

Compatibility with Crystal 0.19.x

Running make test with the latest upgrade to the crystal language (v0.19.0) results in a syntax error. It appears to original from the breaking change to remove the x as Y syntax, noted in the release notes.

Error message:

crystal spec $(find ./spec/unit/ -name '*_spec.cr')
Error in line 1: while requiring "././spec/unit//client_spec.cr"

in ./spec/unit/client_spec.cr:1: while requiring "../spec_helper"

require "../spec_helper"
^

in ./spec/spec_helper.cr:4: while requiring "../src/cossack"

require "../src/cossack"
^

in ./src/cossack.cr:4: while requiring "./cossack/**"

require "./cossack/**"
^

in ./src/cossack/client.cr:47: macro didn't expand to a valid program, it expanded to:

================================================================================
--------------------------------------------------------------------------------
   1. 
   2.       def get(url : String, params : Params? = nil) : Response
   3.         get(url, params) { }
   4.       end
   5. 
   6.       def get(url : String, params : Params? = nil) : Response
   7.         uri = complete_uri!(URI.parse(url))
   8. 
   9.         if params
  10.           query = HTTP::Params.build do |form|
  11.             (params as Params).each { |name, val| form.add(name, val) }
  12.           end
  13.           if uri.query
  14.             uri.query = [uri.query, query].join("&")
  15.           else
  16.             uri.query = query
  17.           end
  18.         end
  19. 
  20.         request = Request.new("GET", uri, @headers.dup, options: @request_options.dup)
  21.         yield(request)
  22.         call(request)
  23.       end
  24.     
  25.       def delete(url : String, params : Params? = nil) : Response
  26.         delete(url, params) { }
  27.       end
  28. 
  29.       def delete(url : String, params : Params? = nil) : Response
  30.         uri = complete_uri!(URI.parse(url))
  31. 
  32.         if params
  33.           query = HTTP::Params.build do |form|
  34.             (params as Params).each { |name, val| form.add(name, val) }
  35.           end
  36.           if uri.query
  37.             uri.query = [uri.query, query].join("&")
  38.           else
  39.             uri.query = query
  40.           end
  41.         end
  42. 
  43.         request = Request.new("DELETE", uri, @headers.dup, options: @request_options.dup)
  44.         yield(request)
  45.         call(request)
  46.       end
  47.     
  48.       def head(url : String, params : Params? = nil) : Response
  49.         head(url, params) { }
  50.       end
  51. 
  52.       def head(url : String, params : Params? = nil) : Response
  53.         uri = complete_uri!(URI.parse(url))
  54. 
  55.         if params
  56.           query = HTTP::Params.build do |form|
  57.             (params as Params).each { |name, val| form.add(name, val) }
  58.           end
  59.           if uri.query
  60.             uri.query = [uri.query, query].join("&")
  61.           else
  62.             uri.query = query
  63.           end
  64.         end
  65. 
  66.         request = Request.new("HEAD", uri, @headers.dup, options: @request_options.dup)
  67.         yield(request)
  68.         call(request)
  69.       end
  70.     
  71.       def options(url : String, params : Params? = nil) : Response
  72.         options(url, params) { }
  73.       end
  74. 
  75.       def options(url : String, params : Params? = nil) : Response
  76.         uri = complete_uri!(URI.parse(url))
  77. 
  78.         if params
  79.           query = HTTP::Params.build do |form|
  80.             (params as Params).each { |name, val| form.add(name, val) }
  81.           end
  82.           if uri.query
  83.             uri.query = [uri.query, query].join("&")
  84.           else
  85.             uri.query = query
  86.           end
  87.         end
  88. 
  89.         request = Request.new("OPTIONS", uri, @headers.dup, options: @request_options.dup)
  90.         yield(request)
  91.         call(request)
  92.       end
  93.     
--------------------------------------------------------------------------------
Syntax error in expanded macro: macro_4395676992:11: unterminated parenthesized expression

            (params as Params).each { |name, val| form.add(name, val) }
            ^

================================================================================

    {% for method in %w(get delete head options) %}
    ^

Host got deformed in redirection

Run:

 #<Cossack::Request:0x55bb428007c0 @method="GET", @uri=#<URI:0x55bb42801360 @scheme="http", @host="172.16.123.129", @port=nil, @path="", @query=nil, @user=nil, @password=nil, @fragment=nil, @opaque=nil>, @headers=HTTP::Headers{"User-Agent" => "Cossack v0.1.4"}, @body=nil, @options=#<Cossack::RequestOptions:0x55bb42807d60 @connect_timeout=30.0, @read_timeout=30.0>>

Redirect:

#<Cossack::Request:0x55bb42800240 @method="GET", @uri=#<URI:0x55bb42801000 @scheme="http", @host="172.16.123.129http", @port=nil, @path="/172.16.123.129", @query=nil, @user=nil, @password=nil, @fragment=nil, @opaque=nil>, @headers=HTTP::Headers{"User-Agent" => "Cossack v0.1.4"}, @body=nil, @options=#<Cossack::RequestOptions:0x55bb42807d60 @connect_timeout=30.0, @read_timeout=30.0>>

I had to overload

class HTTPConnection < Connection
    def call(request : Request) : Response

And add prints there to track it down

Any plans to add proxy support?

The Crystal standard library doesn't contain support for proxy servers. It seems like this would be a great thing for cossack to support. Any plans to add it?

Here's the discussion in the crystal-lang repo with a reference implementation:

crystal-lang/crystal#2963

Thanks!

Nick

HTTPConnection#call passes in full request URI to HTTP::Client#exec

Issue Summary

I'm attempting to record & replay HTTP interactions using Hi8 and Cossack. Hi8 ends up recording the request with the scheme and host "doubled". E.g., "https://api.fixer.io/latest" becomes "https://api.fixer.iohttps://api.fixer.io/latest". See Hi8 issue #2 for details.

I've traced it all the way back to Cossack's HTTPConnection#call where in http_connection.cr:5 it first creates the HTTP::Client by passing in the request.uri, then in http_connection.cr:9 it once again passes the full request.uri.to_s to HTTP::Client#exec(method : String, path, headers, body) which expects only the path component.

Relevant Code
  class HTTPConnection < Connection
    def call(request : Request) : Response
      client = HTTP::Client.new(request.uri)
      client.connect_timeout = request.options.connect_timeout
      client.read_timeout = request.options.read_timeout

      http_response = client.exec(request.method, request.uri.to_s, request.headers, request.body)
Expected Behaviour

Cossack should only pass in the trailing URI path and query components into the HTTP::Client#exec() call.

When HI8 code calls @request.resource.to_s (episode.cr:47), it should only get the path component of the URI.

Actual Behaviour

Because Cossack passes in the full URI, when HI8 calls @request.resource.to_s it returns the full URI. HI8 then appends that to the request header (which already contains the scheme and host components), which leads to the "doubling" of the URI base URL.

Environment

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.