Giter Club home page Giter Club logo

httpi's Introduction

HTTPI

A common interface for Ruby's HTTP libraries. This project is now in maintenance mode. For new projects, we recommend faraday.

Documentation

Development

Installation

HTTPI is available through Rubygems and can be installed via:

$ gem install httpi

or add it to your Gemfile like this:

gem 'httpi', '~> 4.0.0'

Usage example

require "httpi"

# create a request object
request = HTTPI::Request.new
request.url = "http://example.com"

# and pass it to a request method
HTTPI.get(request)

# use a specific adapter per request
HTTPI.get(request, :curb)

# or specify a global adapter to use
HTTPI.adapter = :httpclient

# and execute arbitary requests
HTTPI.request(:custom, request)

# add a client setup block that will be called before each request
HTTPI.adapter = :httpclient
HTTPI.adapter_client_setup = proc do |x|
  x.ssl_config.set_default_paths
  x.force_basic_auth = true
end
# ...
HTTPI.get(request) do |x|
  x.force_basic_auth = false
end

SOCKS Proxy Support

To use the the SOCKS proxy support, please add the socksify gem to your gemfile, and add the following code:

require 'socksify'
require 'socksify/http'

to your project.

Documentation

Continue reading at https://www.rubydoc.info/gems/httpi

httpi's People

Contributors

benoist avatar bvicenzo avatar c960657 avatar carlhoerberg avatar carlzulauf avatar chetan avatar coldnebo avatar connorhd avatar dbackeus avatar dim avatar envek avatar etehtsea avatar fagiani avatar gonzalo-bulnes avatar ioquatix avatar jheiss avatar mrpasquini avatar olleolleolle avatar pcai avatar pchambino avatar pmorton avatar rogerleite avatar rubiii avatar saghaulor avatar tbolender avatar tjarratt avatar turboladen avatar vangberg avatar watson avatar webhoernchen 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  avatar  avatar  avatar  avatar  avatar  avatar

httpi's Issues

License missing from gemspec

Some companies will only use gems with a certain license.
The canonical and easy way to check is via the gemspec,

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Even for projects that already specify a license, including a license in your gemspec is a good practice, since it is easily
discoverable there without having to check the readme or for a license file. For example, it is the field that rubygems.org uses to display a gem's license.

For example, there is a License Finder gem to help companies ensure all gems they use
meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough
issue that even Bundler now generates gems with a default 'MIT' license.

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), github has created a license picker tool.

In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :).

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue and let me know. In either case, I'll follow up. Thanks!

p.s. I've written a blog post about this project

SSL options to not work with `NET::HTTP`

I am trying to use the Savon Soap Client version 2.0.2 to communicate with an api over https and I cannot get the SSL configurations to work when using NET::HTTP. I get cert errors on every request, even if I set config.ssl_verify_mode :none. If I switch to HTTPCLIENT I never get cert errors...

missing headers

I'm using savon with httpclient adapter and I'm missing response headers .
Looking into code, found a line in httpclient.rb(line: 93) where the headers are lost.
In Ruby 1.8.7 that line should be written:

Response.new response.code, Hash[*response.header.all.flatten], response.content

Notice the splat (*) operator.

Connection Options for em-httprequest

If I'm right, on Savon, to create a connection with timeout options, you do something like

client = Savon.client(wsdl: wsdl_content, open_timeout: 60, read_timeout: 120)

but on em-httprequest (version 1.0.3), the class HttpConnectionOptions, which has a constructor where it expects the uri and the options, never gets the options (which if I'm right, should be :connect_timeout and :inactivity_timeout).

later when I call an operation, with:

client.call(:my_operation, message: my_message)

on Savon::Operation.call! the request is created by using HTTPI, and when it tries to do the request, on:

HTTPI::request, the line of code:

adapter_class = load_adapter(adapter, request)

loads the adapter HTTPI::Adapter::EmHttpRequest

but when I check the adapter connection, I get:

(rdb:1) adapter_class.client
<EventMachine::HttpConnection:0x007fc2cb538208 @deferred=true, @middleware=[], @connopts=#<HttpConnectionOptions:0x007fc2cb538e88 @connect_timeout=5, @inactivity_timeout=10, @tls={}, @proxy=nil, @host="my_host.com", @port=443>, @uri="https://my_url.com/my_path">

so you can see that the connection_timeout is 5, and the inactivity_timeout is 10, and the HTTPI::Request that is used to build the EventMachine::HttpConnection is:

#<HTTPI::Request:0x007fc2cab23fd8
 @body=
  "MY_BODY_REQUEST",
 @headers=
  {"MY_HEADER"},
 @open_timeout=60,
 @read_timeout=120,
 @url=#<URI::HTTPS:0x007fc2ca84f7a8 URL:https://my_url.com/my_path>>

in few words, I cannot use timeout options with em-httprequest

Net::HTTP Adapter

By supporting the lowest common denominator, Net::HTTP from stdlib, HTTPI opens up compatability with tools built on a common standard, such as FakeWeb HTTP mocking, New Relic application monitoring, and the http persistent connections gem. Without this adapter, people using these tools will be unable to use gems that are built on HTTPI.

Getting ArgumentError: odd number of arguments for Hash

I changed the respond_with method in httpclient.rb to the following to eliminate the issue - not sure if it's the proper fix:

  def respond_with(response)
    Response.new response.code, Hash.new(response.header.all.flatten), response.content
  end

ArgumentError: odd number of arguments for Hash
from /opt/portal_light/vendor/gems/httpi-0.6.0/lib/httpi/adapter/httpclient.rb:94:in []' from /opt/portal_light/vendor/gems/httpi-0.6.0/lib/httpi/adapter/httpclient.rb:94:inrespond_with'
from /opt/portal_light/vendor/gems/httpi-0.6.0/lib/httpi/adapter/httpclient.rb:66:in do_request' from /opt/portal_light/vendor/gems/httpi-0.6.0/lib/httpi/adapter/httpclient.rb:25:inget'
from /opt/portal_light/vendor/gems/httpi-0.6.0/lib/httpi.rb:83:in get' from /opt/portal_light/vendor/gems/httpi-0.6.0/lib/httpi.rb:147:inwith'
from /opt/portal_light/vendor/gems/httpi-0.6.0/lib/httpi.rb:81:in get' from /opt/portal_light/vendor/gems/savon-0.8.0.beta.1/lib/savon/wsdl/request.rb:21:inresponse'
from /opt/portal_light/vendor/gems/savon-0.8.0.beta.1/lib/savon/wsdl/request.rb:30:in with_logging' from /opt/portal_light/vendor/gems/savon-0.8.0.beta.1/lib/savon/wsdl/request.rb:21:inresponse'
from /opt/portal_light/vendor/gems/savon-0.8.0.beta.1/lib/savon/wsdl/document.rb:88:in http_request' from /opt/portal_light/vendor/gems/savon-0.8.0.beta.1/lib/savon/wsdl/document.rb:72:indocument'
from /opt/portal_light/vendor/gems/savon-0.8.0.beta.1/lib/savon/wsdl/document.rb:100:in parser' from /opt/portal_light/vendor/gems/savon-0.8.0.beta.1/lib/savon/wsdl/document.rb:38:inendpoint'
from /opt/portal_light/vendor/gems/savon-0.8.0.beta.1/lib/savon/client.rb:101:in `preconfigure'

Split adapters into own gems

I'm thinking of adding support for patron and noticed all the different adapters are bundled into httpi (and require'd regardless). What about splitting them out and let the user install/require the one they wish to use?

e.g.

 require "httpi-curb"

Requiring the adapter invokes something like:

which hooks it all up as well as instructing HTTPI to use curb. I'd be happy to contribute code for this, assuming it's not a terrible idea :)

Setting HTTPI.log_level doesn't have an effect on anything

The documentation tells you that you can do the following to set log level:

HTTPI.log_level = :warn

The problem is that log_level does not get used anywhere. There is only one place that calls HTTPI.log and that is HTTPI.with_adapter. There log gets called with the explicit :debug level.

I see two options here:

  1. Change HTTPI.with_adapter to rely on the configured log level
  2. Remove log_level support and document that :default always gets used

Which way should we go?

204 response from server causes exception

a 204 is per definition without a body which causes line 52 in response.rb to toss an exception when trying to get a range on a nil body.

When I insert some puts in initialize I show:
Status Code : 204
Headers: {"server"=>"Netscape-Enterprise/6.0", "date"=>"Wed, 05 Jan 2011 09:52:31 GMT", "content-type"=>"text/html", "content-length"=>"0"}

There are of-course the other responses that are without a body too. A check for the body length somewhere is probably needed, right?

JRuby requires ssl version to be a string

The JRuby version of httpclient requires that the ssl_version configuration be a string.

I've made a change to file:

lib/httpi/adapter/httpclient.rb

line 64 was:
@client.ssl_config.ssl_version = ssl.ssl_version if ssl.ssl_version

changed to:
@client.ssl_config.ssl_version = ssl.ssl_version.to_s if ssl.ssl_version

This change doesn't seem to hurt native ruby, but I'm not sure about other implementations (rubinius, etc). I also suspect that the other adapters may need a similar change, but I'm not able to test that at the moment.

Sorry about the pull request the really isn't. I've been sitting on this change for months in anticipation of spending the time to figure out how to do a proper pull request, but thought it was better to get the fix out there than delay until I actually got a clue about git and github (and wrote tests, etc).

update ntlm-http dependency

not sure what to do here :

https://github.com/trampoline/ntlm-http/tree/new-version-0.1.2.1

fixes

  • KConv compatability issues in net/ntlm when running under JRuby
  • issues with ntlm authentication when a windows domain must be specified

but there seem to be several versions of ntlm-http gem floating around already and i have no idea which is authoritative

http://rubygems.org/search?utf8=%E2%9C%93&query=ntlm-http

as it is, installing savon+httpi gets you an ntlm-http which won't work against windows soap services which require ntlm auth with a windows domain, which is just about every exchange-web-services instance in the wild, and probably many other services too

:c

Encoding Hashes into POSTable bodies

Hello :)

I found out that some adapters do encode Hashes passed as post-bodies into postable-strings (httpclient, for example). Other adapters (Curb, for example) doesn't.

Do you think this should be fixed:

a) in each adapter
b) from HTTPI side (to avoid incompatible implementations (?))
c) in my code

Thanks!

More adapters

Is there any reason why httpi doesn't support the following libraries:

  • Httparty
  • Patron
  • Typhoeus
  • Excon

Too many open files.

/1.9.1/net/http.rb:644:in `initialize': Too many open files - socket(2) (Errno::EMFILE)
/1.9.1/net/http.rb:644:in `open'
/1.9.1/net/http.rb:644:in `block in connect'
/1.9.1/timeout.rb:58:in `timeout'
/1.9.1/timeout.rb:89:in `timeout'
/1.9.1/net/http.rb:644:in `connect'
/1.9.1/net/http.rb:637:in `do_start'
/1.9.1/net/http.rb:626:in `start'
/gems/httpi-1.1.1/lib/httpi/adapter/net_http.rb:75:in `do_request'
/gems/httpi-1.1.1/lib/httpi/adapter/net_http.rb:22:in `get'
/gems/httpi-1.1.1/lib/httpi.rb:86:in `block in get'
/gems/httpi-1.1.1/lib/httpi.rb:193:in `with_adapter'
/gems/httpi-1.1.1/lib/httpi.rb:84:in `get'
/gems/httpi-1.1.1/lib/httpi.rb:133:in `request'

update httpclient dependency

version 2.1.7.2 fixes NTLM authentication problem which prevented savon working against Exchange Web Services when a windows domain was required for authentication

Thread safety

HTTPI doesn't seem to be thread safe because of global state. This is bad :(

Also related to #73

NTLM response causing Net::HTTPBadResponse

On version rubyntlm (0.3.1):

Failures:

  1) HTTPI::Adapter::NetHTTP http requests supports ntlm authentication
     Failure/Error: response = HTTPI.get(request, adapter)
     Net::HTTPBadResponse:
       wrong status line: "ntlm-authHTTP/1.1 200 OK"
     # ./lib/httpi/adapter/net_http.rb:42:in `block in request'
     # ./lib/httpi/adapter/net_http.rb:66:in `call'
     # ./lib/httpi/adapter/net_http.rb:66:in `block in do_request'
     # ./lib/httpi/adapter/net_http.rb:64:in `do_request'
     # ./lib/httpi/adapter/net_http.rb:33:in `request'
     # ./lib/httpi.rb:138:in `request'
     # ./lib/httpi.rb:104:in `get'
     # ./spec/httpi/adapter/net_http_spec.rb:67:in `block (3 levels) in <top (required)>'

Version rubyntlm (0.1.1) is ok.
This issue is a reminder to check rubyntlm project.

Certificate verification not working correctly?

Hi,

if using client authentication with ssl certificates there seems a problem when verifying the
servers ssl CA certificates (using httpclient).
The root CA certficate is set like
http.auth.ssl.ca_cert_file='db_root_ca_7.pem'
But in httpclient.rb it is set to client_ca (in httpclient adapater):
client.ssl_config.client_ca = ssl.ca_cert if ssl.ca_cert_file

When i correct this to
client.ssl_config.set_trust_ca(ssl.ca_cert_file) if ssl.ca_cert_file
it works as expected and the CA file is used to verify the servers certificate.

Regards,
Roland

No request logging

The readme says that by default HTTP requests are logged to STDOUT. This does not appear to be the case, even when I set HTTPI.log = true. How can I log the request and response payloads for debugging purposes?

HTTPI is truncating response headers

Some evidence:

$ curl -I http://br.yahoo.com
[...]
Set-Cookie: IU=deleted; expires=Mon, 28-Nov-2011 13:05:46 GMT; path=/; domain=.yahoo.com
Set-Cookie: PH=deleted; expires=Mon, 28-Nov-2011 13:05:46 GMT; path=/; domain=.yahoo.com
Set-Cookie: MSC=t=1354021547X; expires=Wed, 27-Nov-2013 13:05:47 GMT; path=/; domain=.yahoo.com
Set-Cookie: fpc=d=pT0Q_yjRlaNbj84q3kJ0Bu4REjib1FNsC106B3kSpU.P9eBX64Ml3SsgKCkjpGmQBrZYZM15huzayuXz0L27ZIv8OnCpswr0kHvK8BWZBXZ4JnfS9wHnXexE9eODzw6FlLJ34eAqNdguDn5uMxUMh2tqped8imj.Y5ghMCQ7HdBqlXwDNN1r1oOt0KXHWEkptCGBre0-&v=2; expires=Wed, 27-Nov-2013 13:05:47 GMT; path=/; domain=br.yahoo.com
Set-Cookie: fpps=deleted; expires=Mon, 28-Nov-2011 13:05:46 GMT; path=/; domain=br.yahoo.com
Set-Cookie: fpt=d=fAgQuh3XeVyQ0SZnx0E2dD4HQyzXrkNQR_Jd_4uKZKR0ewy2D_vne_SmtTyH1VlczCWGQ4gL4eAByIwWDuNYn9u7QBrSncNoDVahgD9_xUzjpSYP4OVswNAvAn4uF46W23Fq34E0bjrs1WCmmvtQ1Dpv8hFMBlRC_kf33_c0bDmLGhXDkPIs6g2OkPIhrv8OjBctFDfx.0yBvQoaO0Ms69FqoDwODKUK.j9JNHF1r_mila0e6IOjPVMytQZVpg1QDXoqqhP4fXAwdrc7ENCjibSB0PM0lkI_qIfhDHJCeyf9akU.DP1KBv2rG4lmbT0ENVx_p67pNuezqCDLoyBR0ugXbD9Wh1hiQgmp1zvYk9iHyi2ZFgeF._z_C0iZ4CXx7UdaxuOHymdES8dJlJoVrCgb7ijKjWnM7EeQgiqFxE9gNqQHsr2tRY11ThSDssQs.RKi0LxwutsFT3b5oBVFJSqOh6kTzUWJIe8ZSfGTMQ0RKRKwxks1rDqju1UfRBBoRVq5DAGSiJOzo8_MykJ8qsL19b9iJm65O5iF_gEG2YrpO3iU8XSYcwPb5tWWGymS1Q--&v=1; path=/; domain=br.yahoo.com
Set-Cookie: fpc_s=d=2zRQRMjRlaPIhaPVoWgXBdq00OJxzfvr16KeQbtQGdVmUbvECiDJkiH5LSUHZtoiSmhazOoHh_1_nTZbCDYQ5cg9uh.WRVa4fo73H6pqeGVe3BZwKSNngqkYOX4xVIs2m3aiDPOaoGqbfAxVx8hOYAFHUhcJ_oJ6T_dxqRWv.rgYkSGZJhceYFJLOl.Locpkhpg1W4XJsfrjC7ywDuFoTB3Ern4XmYP2ncrB5KWohx4IpXLKqIiMsdtLrvjt6w7UQhSpDrJXcA_gwvT9B7PKSxy2ETMK1OsY.4y.RvZpnzGc.us7.d59NSFdQMkQSbrpwIM5agg8DiofQiBxIakBp_6SzmsWAqejLButP.GMkJAms2_UixKAYko9TpLzfWeNB0GzGTeNetu4zE3Er2R6KsOugwgV7SkVsfgrdU75iiiwveMn&v=2; path=/; domain=br.yahoo.com
[...]

Using a simple script (httpi 2.0.0.rc1), i realized that only curb adapter return all "Set-Cookie" headers.

HTTPI.log = true
[:net_http, :httpclient, :curb].each do |adapter|
  request = HTTPI::Request.new("http://br.yahoo.com")
  request.headers = {"User-Agent" => "curl/7.21.4"}
  response = HTTPI.get(request, adapter)
  puts "Set-Cookie: #{response.headers["Set-Cookie"].inspect}"
end

Results:

D, [2012-11-27T11:03:16.562429 #41548] DEBUG -- : HTTPI GET request to br.yahoo.com (net_http)
Set-Cookie: "IU=deleted; expires=Mon, 28-Nov-2011 13:03:12 GMT; path=/; domain=.yahoo.com"

D, [2012-11-27T11:03:21.086947 #41548] DEBUG -- : HTTPI GET request to br.yahoo.com (httpclient)
Set-Cookie: "fpc_s=d=e.AfOJJslaP77_ZLGuCCmy9bbCmZApcoySYRckZpfsFCEFQgFVg9Z6CMxocrOtzuVAIrQuUtt28S1mqpXveqZ5ca83Kc.T7LSUbNId6CfYoxp70q7KeLbcLVgxezcpXACefDxG2AaupWVzzoLh7CZLoQk33Ei5fezikXbJMIGEpzOdF.ys0WqlJWRsolZP4LZ0oRADoIOydKwaF2VMXECDpX_A0UWa9js1CkiJ.DlGvM4sZjM18KRNzL_9uRI.MULS0ytpLfQfK0xGog2sirqj05a74Q9SCtdcA13s5Tj3PjwuAZnxxSzJnTyDwrdSscKvsiw3.UNg5oqLdQ5fgSEX7oBRaUvWWkVBVH_cvPr8RB9e.T2jJTKMUZ.tDd2E3aZ4mQ2htpHbkBEzgfMzbbKjbYIJF2avg8GvOQsRGf3SSkheeH&v=2; path=/; domain=br.yahoo.com"

D, [2012-11-27T11:03:22.969444 #41548] DEBUG -- : HTTPI GET request to br.yahoo.com (curb)
Set-Cookie: ["IU=deleted; expires=Mon, 28-Nov-2011 13:03:19 GMT; path=/; domain=.yahoo.com", "PH=deleted; expires=Mon, 28-Nov-2011 13:03:19 GMT; path=/; domain=.yahoo.com", "MSC=t=1354021400X; expires=Wed, 27-Nov-2013 13:03:20 GMT; path=/; domain=.yahoo.com", "fpc=d=twmBb_tilaM2g8UhO2xUJ267pR5WJEyQjQBCKZ6P99Py8EcPbZnnJYuWtk6.dDsQcOtpR6NXZ8_n37uA2hmXRRyS60QoSnbBh4llNfxyPNleDwnFykzKyE0JRevgDtN8Wc3N_Rx9I4QZb9r9aVwkfaKEYJdlXxUpe37gqYuoHmiuWuzze1AkdL96T3icYn_LQJACNtc-&v=2; expires=Wed, 27-Nov-2013 13:03:20 GMT; path=/; domain=br.yahoo.com", "fpps=deleted; expires=Mon, 28-Nov-2011 13:03:19 GMT; path=/; domain=br.yahoo.com", "fpt=d=cgP9GTbXeVzKcBBu441lu6snPn5G0OxnEsu2HHFRGns2MWR.hszVlrrBI4SsPg.oknioT7TkHxn.hYhTwUwn..8CnrM7pu4iYnxuV6MgpPniQAQbb2glPUjTcr1z.CbH8RQA42th7C9L0gVOQDltnmxPv_2OFp76xDs.MpAoaqAVPbXClozyDh6tRw4CCllehQw2f7TQsFxHyi9I50sTyNOAmUcOpejEP1jJjAZfY.F5.h9poAtTiov.Yz.8UjELZSVNZKgn6vnDw9VmQUUTEI45iqiLGCaZSlgzxv1pbOh7KqihVY5itiWBMIVZn51X0huBWDv07bZjXxgXAVHel5i9QBzGBfUw0AmDPn2e56dT44_lvrK5U1WpNSkjcOU2nVZ_3wkf0ClKEg8AymM3k5ZDtVd4SIT5VSv8c332gLFvY4VKEMkH1et.A6SWH79TtkXVoPViOvJT978GWiEKJFpU1H7W3kzAtfeUKVnZnzMQ7udTVXON9_Mxhyu.B0pZyysv4mEc.rXLjOoF7CU1J7rP3T6MNZBYQwAxgH2qkLPoNecOmlTmfNsgVXjRXAgQLw--&v=1; path=/; domain=br.yahoo.com", "fpc_s=d=dcozG8hilaMbWa30O6JWUesgDD1W_k_SBg3VMdMWl3S0sFfGT5hPgeGEpvStnJj1BKsXkzQhhdn0gx7L2XN79Bu5SMBVb4.xrtHR.x6YMgRib4B7MPsR3l4rL8dS_EAeTJmGOeadUph6WQeZokCsb3t66iOVnZ3fxfDt_7KkS9EfiJMblqYywobLceiOhIjwgKfFVmm0XsyahY_PDWmD6MyjgcCJQPmM7QVhP_mMWB5rSNjSHI3KzP24COyBbGgrdNQE4MzrFu8xL.Q7TDiCMZcCZec352gsvVXTK_y59W7b9F73Fhq4d_sfFLHh4nSDbixXEYN__Tv2O8Hl7.HA9QR.jbP2iO1HIELslzXg1cAOxPkXpelfEhLsWQJsTRp0rJwFMy5JrkvTwLjWgdAR6soo7w_1FFgLu.vEmbGA.eKjy3cO&v=2; path=/; domain=br.yahoo.com"]

I'm planning to work on net_http and httpclient adapters to return headers like curb do. Is that ok?

httpclient / verify mode - why doesnt httpi just pass this through?

Hi,

I am testing a site that requires me to use client certificates.

However the SSL cert on the server is a self-signed test certificate.

So, if I use the default verify mode, it fails due to the self-signed certificate.

If I turn off the verify mode, then httpi does not pass the client cert details through to httpclient and so they are not sent with the connection.

httpclient.rb

      def setup_ssl_auth
        ssl = @request.auth.ssl

        unless ssl.verify_mode == :none
          @client.ssl_config.client_cert = ssl.cert
          @client.ssl_config.client_key = ssl.cert_key
          @client.ssl_config.add_trust_ca(ssl.ca_cert_file) if ssl.ca_cert_file
        end

        @client.ssl_config.verify_mode = ssl.openssl_verify_mode
        @client.ssl_config.ssl_version = ssl.ssl_version if ssl.ssl_version
      end

Why not just always pass the client_cert/key info through to httpclient and let httpclient handle the verify mode?

Thanks,
Chris

PS Will give that a try now...

NoMethodError: undefined method `to_hash' for nil:NilClass

Hi
This bug was reported under the Savon Project Issue 163
Savon 0.8.6 not playing nicely with Httpi 0.9.0 ?
https://github.com/rubiii/savon/issues/#issue/163

Error occurs after bug fix in Issue 22
https://github.com/rubiii/httpi/issues/closed#issue/22

Rolling httpi back to 0.7.9 solves the problem with Savon

Here is the Exception:
HTTPI executes HTTP GET using the net_http adapter
NoMethodError: undefined method to_hash' for nil:NilClass from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/whiny_nil.rb:48:inmethod_missing'
from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/httpi-0.9.0/lib/httpi/adapter/net_http.rb:111:in respond_with' from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/httpi-0.9.0/lib/httpi/adapter/net_http.rb:76:indo_request'
from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/httpi-0.9.0/lib/httpi/adapter/net_http.rb:22:in get' from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/httpi-0.9.0/lib/httpi.rb:86:inblock in get'
from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/httpi-0.9.0/lib/httpi.rb:189:in with_adapter' from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/httpi-0.9.0/lib/httpi.rb:84:inget'
from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/savon-0.8.6/lib/savon/wsdl/request.rb:21:in block in response' from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/savon-0.8.6/lib/savon/wsdl/request.rb:30:inwith_logging'
from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/savon-0.8.6/lib/savon/wsdl/request.rb:21:in response' from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/savon-0.8.6/lib/savon/wsdl/document.rb:93:inhttp_request'
from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/savon-0.8.6/lib/savon/wsdl/document.rb:77:in document' from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/savon-0.8.6/lib/savon/wsdl/document.rb:105:inparser'
from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/savon-0.8.6/lib/savon/wsdl/document.rb:30:in namespace' from (irb):9 from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/railties-3.0.3/lib/rails/commands/console.rb:44:instart'
from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/railties-3.0.3/lib/rails/commands/console.rb:8:in start' from /Users/miqe/.rvm/gems/ruby-1.9.2-p0/gems/railties-3.0.3/lib/rails/commands.rb:23:in<top (required)>'
from script/rails:6:in require' from script/rails:6:in

'

This is the first bug report I have ever filed. How do I add the Bug label?

Argument error on logging adapter warning.

Noticed this using Savon - the error appears to affect only the 0.8.0 release.

In the 0.7.x series, HTTPI::Adapter would use the HTTPI.log proxy logging method, which takes an argument splat. In 0.8.0, it uses HTTPI.logger.warn which takes only one argument - since two strings are still being passed, an ArgumentError is raised.

ArgumentError: wrong number of arguments (2 for 1)
from .../vendor/bundler_gems/ruby/1.8/gems/httpi-0.8.0/lib/httpi/adapter.rb:60:in `warn'
from .../vendor/bundler_gems/ruby/1.8/gems/httpi-0.8.0/lib/httpi/adapter.rb:60:in `load_adapter'
from .../vendor/bundler_gems/ruby/1.8/gems/httpi-0.8.0/lib/httpi/adapter.rb:45:in `find'
from .../vendor/bundler_gems/ruby/1.8/gems/httpi-0.8.0/lib/httpi.rb:186:in `with_adapter'
from .../vendor/bundler_gems/ruby/1.8/gems/httpi-0.8.0/lib/httpi.rb:84:in `get'
from .../vendor/bundler_gems/ruby/1.8/gems/savon-0.8.6/lib/savon/wsdl/request.rb:21:in `response'
from .../vendor/bundler_gems/ruby/1.8/gems/savon-0.8.6/lib/savon/wsdl/request.rb:30:in `with_logging'
from .../vendor/bundler_gems/ruby/1.8/gems/savon-0.8.6/lib/savon/wsdl/request.rb:21:in `response'
from .../vendor/bundler_gems/ruby/1.8/gems/savon-0.8.6/lib/savon/wsdl/document.rb:93:in `http_request'
from .../vendor/bundler_gems/ruby/1.8/gems/savon-0.8.6/lib/savon/wsdl/document.rb:77:in `document'
from .../vendor/bundler_gems/ruby/1.8/gems/savon-0.8.6/lib/savon/wsdl/document.rb:105:in `parser'
from .../vendor/bundler_gems/ruby/1.8/gems/savon-0.8.6/lib/savon/wsdl/document.rb:38:in `endpoint'
from .../vendor/bundler_gems/ruby/1.8/gems/savon-0.8.6/lib/savon/client.rb:108:in `preconfigure'
from .../vendor/bundler_gems/ruby/1.8/gems/savon-0.8.6/lib/savon/client.rb:74:in `request'

Current stateless design break Keep-Alive support

Currently a new adapter is instantiated for each HTTP request. It mean that a new HTTPClient or Net::HTTP instance is created too, and it's bad because it prevent them to store TCP connections in order to support the HTTP 1.1 keep alive feature which is a huge performance gain when you have to make multiple request on the same server.

Curb adapter returns incorrect headers

> HTTPI.get("http://example.com").headers
=> {"Server"=>"Apache", "Last-Modified"=>"Fri, 30 Jul 2010 15:30:18 GMT", "ETag"=>""573c1-254-48c9c87349680"", "Accept-Ranges"=>"bytes", "Content-Type"=>"text/html; charset=UTF-8", "Connection"=>"Keep-Alive", "Date"=>"Mon, 01 Nov 2010 03:58:52 GMT", "Age"=>"80     ", "Content-Length"=>"596"}                               
> HTTPI.get("http://example.com", :curb).headers
=> {} 

Curl::Easy#headers returns the request headers, not the response headers. To get the headers of the response, you'll have to parse the header string yourself.

You can see what I did to implement curb support in Webmock (I borrowed the header parsing stuff from Patron):

http://github.com/bblimke/webmock/blob/master/lib/webmock/http_lib_adapters/curb.rb#L86
http://github.com/bblimke/webmock/blob/master/lib/webmock/http_lib_adapters/curb.rb#L235

Fix Travis banner

Travis is red on readme. :-(
It seems to pointing to old repository from rubiii.

Send client certificate even when ssl_verify_mode is :none

In httpi 2.0.0, httpi disables the use of client certificates when request.auth.ssl.verify_mode is set to :none. This can cause problems when a server requires a client-side certificate but the server itself uses a certificate with "problems" (ie. self-signed or expired). The client should always be able to send a certificate even if the server certificate has problems.

It appears the issue is in each of the adapters in HTTPI::Adapter in the setup_ssl_auth method. This problem is present in at least the Net::HTTP and Curb (have not tried the others yet).

get rid of global state

it prevents e.g. using multiple loggers for HTTPI in one project.
i would like to see all methods on the HTTPI module which deal with global state gone.
i already did this for several savonrb libraries including nori for the savon 2.0 release.

here's the list of methods that come to mind:

  • HTTPI.adapter=
  • HTTPI.log=
  • HTTPI.logger=
  • HTTPI.log_level=

maybe, if we changed the HTTPI module to a class, we could create HTTPI instances which hold these options. the static http request method on the new HTTPI class like .post could then be changed to shortcuts for creating a new instance with options and executing a request.

don't know if that's the best idea though.

ssl server authentication

Hello everyone

I'm connecting to a biztalk SOAP API, and I've been given a public cert from the server to use to connect using ssl server authentication.

ruby 1.9.2, curb (0.7.15),savon (0.9.1) httpi (0.9.2)

I can't seem to get it to work properly.

It works from the command line with curl

curl --cacert /path/to/cert https://raadeeraa

but I can't work out the combination of how to get it to work with savon, httpi and curb

This goes through

http.auth.ssl.ca_cert_file = '/path/to/cert'
http.auth.ssl.verify_mode = :peer

But this also goes through, so I don't think it's working properly

http.auth.ssl.ca_cert_file = '/complete/load/of/nonsnse'
http.auth.ssl.verify_mode = :peer

This fails with a ssl cert error

http.auth.ssl.ca_cert_file = '/path/to/cert'
http.auth.ssl.verify_mode = :none

cert=': undefined methodrindex' for nil:NilClass (NoMethodError)

So I specify a cert as well

http.auth.ssl.ca_cert_file = '/path/to/cert'
http.auth.ssl.cert_file = '/path/to/cert'
http.auth.ssl.verify_mode = :none

rails3.0.4/gems/httpi-0.9.2/lib/httpi/adapter/curb.rb:29:in `http_post': Problem with the local SSL certificate (Curl::Err::SSLCertificateError)

Please don't think I'm posting without reading, I've read all these pages and can't find a solution

Well, you'll have to take my word for it, i can only put up 2 hyperlinks :-)

http://stackoverflow.com/questions/40273/whats-the-best-way-to-use-soap-with-ruby
http://stackoverflow.com/questions/3133065/talking-with-a-soap-service-using-savon-gem-in-ruby
http://rubiii.github.com/savon/
http://blog.nofail.de/2010/03/nosql-rails-models-with-soap/
http://stackoverflow.com/questions/2209105/help-soap-response-using-ssl-basic-authentication-and-client-certificates
http://stackoverflow.com/questions/5047797/trouble-using-a-ssl-certificate-self-signed-certificate-in-certificate-chain
http://savonrb.com
http://fagiani.github.com/savon/#the_http_object
http://rubydoc.info/gems/httpi/0.9.2/frames
https://github.com/rubiii/httpi

Any suggestions will be greatly appreciated.

Request does not yield adapter client on v2.0.0.rc1

# using version 1.1.1
request = HTTPI::Request.new("http://google.com")
response = HTTPI.get(request, :curb)
puts response.code  # => 301

response = HTTPI.get(request, :curb) do |client|
  client.follow_location = true
end
puts response.code  # => 200

# using version 2.0.0.rc1
request = HTTPI::Request.new("http://google.com")
response = HTTPI.get(request, :curb)
puts response.code  # => 301

response = HTTPI.get(request, :curb) do |client|
  # this block is not called
  client.follow_location = true
end

# this works!
response = HTTPI.request(:get, request, :curb) do |client|
  client.follow_location = true
end
puts response.code  # => 200

I can work on this. Ok?

Roger Leite

Unified HTTP Exceptions?

I would love to have httpi catch (rescue) and re-throw all adapter exceptions so that client code (e.g. my Savon SOAP client) could be a bit cleaner in its exception handling.

A connection timeout, a connection refused, a internal server error... they are all different between the libraries and also not always in a "uniform" structure within each adapter.

In a SOAP client I may want to distinguish all http related errors from SOAP errors and respond to them in a certain way as a group. I may want to try a backup endpoint, for example. Something I would not want to do for SOAP exceptions but which might be a good idea for timeouts and server errors.

I haven't looked at all adapters in detail to inventory the possible exceptions in full. Excon had them all nicely bundled together... about 45-48 of them it looks like. https://github.com/geemus/excon/blob/master/lib/excon/errors.rb

What do you think? Good idea? Bad idea? A lot of work?

Checklist for release v2.1.0

Pending by topics.

New adapters:

  • #91 - Added support for Excon
  • #92 - Net::HTTP::Persistent adapter

Bugs:

  • #88 - Connection Options for em-httprequest
  • #90 - Should raise exception if trying to use digest auth with net_http adapter

To next release:

  • #87 - NTLM Support with Full Domain and Server Authentication

I think we can merge the new adapters and should be great fix the bugs, before release. What do you say @rubiii ?

httpclient is broken in ruby 2.0

Guys, gals; thanks for HTTPI, it makes my life better.

It seems that httpclient is broken in ruby 2.0 (see nahi/httpclient#171 ); so I think the adapter fallback chain should be different when running under 2.0,

Maybe by removing httpclient [:curb, :em_http, :excon, :net_http, :net_http_persistent] or at least moving it after :excon, like in [:curb, :em_http, :excon, :httpclient, :net_http, :net_http_persistent]

Thanks a lot

Puma 2.1.0 returning empty Headers on HEAD request

Using puma 2.1.0, tests of all adapters during HEAD requests are returning empty HTTP headers.

Failures:

  1) HTTPI::Adapter::NetHTTP http requests executes HEAD requests
     Failure/Error: response.headers["Content-Type"].should eq("text/plain")

       expected: "text/plain"
            got: nil

       (compared using ==)
     # ./spec/httpi/adapter/net_http_spec.rb:40:in `block (3 levels) in <top (required)>'

  2) HTTPI::Adapter::Curb http requests executes HEAD requests
     Failure/Error: response.headers["Content-Type"].should eq("text/plain")

       expected: "text/plain"
            got: nil

       (compared using ==)
     # ./spec/integration/curb_spec.rb:51:in `block (3 levels) in <top (required)>'

  3) HTTPI::Adapter::EmHttpRequest http requests executes HEAD requests
     Failure/Error: response.headers["Content-Type"].should eq("text/plain")

       expected: "text/plain"
            got: nil

       (compared using ==)
     # ./spec/integration/em_http_spec.rb:60:in `block (3 levels) in <top (required)>'
     # ./spec/integration/em_http_spec.rb:14:in `block (3 levels) in <top (required)>'

 4) HTTPI::Adapter::HTTPClient http requests executes HEAD requests
     Failure/Error: response.headers["Content-Type"].should eq("text/plain")

       expected: "text/plain"
            got: nil

       (compared using ==)
     # ./spec/integration/httpclient_spec.rb:48:in `block (3 levels) in <top (required)>'

  5) HTTPI::Adapter::NetHTTP http requests executes HEAD requests
     Failure/Error: response.headers["Content-Type"].should eq("text/plain")

       expected: "text/plain"
            got: nil

       (compared using ==)
     # ./spec/integration/net_http_spec.rb:48:in `block (3 levels) in <top (required)>'

Finished in 2.46 seconds
329 examples, 5 failures, 1 pending

Using puma 2.0.1, all tests are passing.

This issue is a reminder to investigate possible bug on puma.

SSL problem

Hey,
Something went wrong with this update. When I'm using HTTPi 1.7.1 all my tests passes. But with this one I got the following error:
SSL_connect SYSCALL returned=5 errno=0 state=SSLv3 read finished A

I'm using the following configuration in my Savon::Client.new:

    http.auth.ssl.verify_mode = :none
    http.auth.ssl.cert_key_password = credential.password
    http.auth.ssl.cert_file = File.expand_path(credential.cert_crt.path)
    http.auth.ssl.cert_key_file = File.expand_path(credential.cert_key.path)

Is there anything wrong with my code? It worked very well until this commit.

Best regards
andersondias

decoded_gzip_body masks exceptions

We're getting NoMethodError: undefined method `close' for nil:NilClass from our application and traced it to the ensure block in HTTPI::Response#decoded_gzip_body.

def decoded_gzip_body
  gzip = Zlib::GzipReader.new StringIO.new(raw_body)
  gzip.read
ensure
  gzip.close
end

Effectively the ensure block is raising because gzip is nil but it's masking what the real exception is. The ensure block should not raise. Maybe add if gzip to the ensure block?

Follow HTTP redirects

The HTTPI library should automaticaly follow HTTP redirects (3xx status codes), at least 301 Moved Permanently, 302 Found, 307 Temporary Redirect, and 308 Permanent Redirect.

Encoding Problem With pyu-ntlm-http

NTLM is currently broken in HTTPI 0.9.4 due to a bug in pyu-ntlm-http 0.1.3.1. On line 104 of lib/net/ntlm.rb (https://github.com/pyu10055/ntlm-http/blob/master/lib/net/ntlm.rb) there is:

swap16(Kconv.kconv(str, Kconv::UTF16, Kconv::ASCII).gsub(/^\376\377/,''))

Which produces the following error:

/ruby/gems/1.9.1/gems/pyu-ntlm-http-0.1.3.1/lib/net/ntlm.rb:104:in `gsub': incompatible encoding regexp match (ASCII-8BIT regexp with UTF-16BE string) (Encoding::CompatibilityError)

The fix would probably as simple as:

regex = Regexp.new(Kconv.kconv("^\376\377", Kconv::UTF16, Kconv::ASCII))
swap16(Kconv.kconv(str, Kconv::UTF16, Kconv::ASCII).gsub(regex,''))

The developer of pyu-ntlm-http is using a standard ASCII regex to replace a character in a UTF-16BE string. I have no idea whether pyu-ntlm-http is still active and whether it's the best NTLM library out there, so I thought I'd let you guys know so you can determine what you want to do here.

I've replied to the patch that caused this problem here: pyu10055/ntlm-http#1

Net::HTTP adapter broken?

ruby-1.9.2-p180 :005 > HTTPI.get 'http://www.example.com'
D, [2011-05-09T21:41:48.430221 #34218] DEBUG -- : HTTPI executes HTTP GET using the net_http adapter
NoMethodError: undefined method `to_hash' for nil:NilClass
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@url_validation/gems/httpi-0.9.3/lib/httpi/adapter/net_http.rb:110:in `respond_with'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@url_validation/gems/httpi-0.9.3/lib/httpi/adapter/net_http.rb:76:in `do_request'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@url_validation/gems/httpi-0.9.3/lib/httpi/adapter/net_http.rb:22:in `get'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@url_validation/gems/httpi-0.9.3/lib/httpi.rb:86:in `block in get'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@url_validation/gems/httpi-0.9.3/lib/httpi.rb:189:in `with_adapter'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@url_validation/gems/httpi-0.9.3/lib/httpi.rb:84:in `get'
    from (irb):5
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.13/lib/bundler/cli.rb:437:in `console'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.13/lib/bundler/vendor/thor/task.rb:22:in `run'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.13/lib/bundler/vendor/thor/invocation.rb:118:in `invoke_task'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.13/lib/bundler/vendor/thor.rb:246:in `dispatch'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.13/lib/bundler/vendor/thor/base.rb:389:in `start'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@global/gems/bundler-1.0.13/bin/bundle:13:in `<top (required)>'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@global/bin/bundle:19:in `load'
    from /Users/tmorgan/.rvm/gems/ruby-1.9.2-p180@global/bin/bundle:19:in `<main>'

gzip data in body gets un-compessed automatically

I am working on an API which return data gzipped on request. This is not an HTTP-level compression but the response compression only.

Case A, headers (problem):
"Content-Type"=>"application/x-gzip; charset=UTF-8"
"Content-Disposition"=> "attachment; filename="report.csv.gz""
@raw_body=> "\037\213\b\000\000\000...."

Case B, headers (works as expected):
"Content-Encoding"=>"gzip"
"Content-Type"=>"text/csv; charset=UTF-8"
@raw_body="\037\213\b\000\000\000...."

For case A expected body is raw gzip, for case B - unpacked CSV.
Actual result for both cases is unpacked CSV.

put in certain circumstances doesn't send authentication

I'm using a horrible rest api with one of the products at work here, and I had an issue with HTTPI + Basic Auth.

If I do a get with the code below, its sends the Authorization header, change it to a put and it stops.

Note, this is probably a problem with :httpclient, cause switching to :curb fixed it, but it should be verified with other adapters.

version is:

ruby 2.0.0-p247
httpi (2.1.0, 2.0.2)
httpclient (2.3.3)

require 'httpi'
require 'json'
require 'uri'

prop = {
"name" => "prop1",
"description" => "blah",
"secure" => false,
"value" => "value1"
}

@url = 'http://host1'
@user = 'admin'
@pass = 'admin'

appId = '2e645851-31cb-45e8-9e26-732631e90872'
envId = '9d815997-b721-4aaf-9501-5fbf0474f679'

HTTPI.log_level = :debug

url = @url + "/property/propSheet/applications&#{appId}&environments&#{envId}&propSheet.-1/propValues"

puts url

prequest = HTTPI::Request.new
prequest.url = url
prequest.auth.basic(@user, @pass)
prequest.open_timeout = 30 # seconds
prequest.read_timeout = 30 # seconds
prequest.body = {
"name" => prop["name"],
"description" => prop["description"],
"secure" => prop["secure"],
"value" => prop["value"]
}.to_json
presponse = HTTPI.get(prequest)
puts(presponse.body)

GET /property/propSheet/applications&2e645851-31cb-45e8-9e26-732631e90872&environments&9d815997-b721-4aaf-9501-5fbf0474f679&propSheet.-1/propValues HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID_8080=82BA9A8359F8668975628C1BFB12E20D
Authorization: Basic YWRtaW46YWRtaW4=
User-Agent: HTTPClient/1.0 (2.3.3, ruby 2.0.0 (2013-06-27))
Accept: /
Date: Wed, 24 Jul 2013 21:15:16 GMT
Content-Length: 69
Host: host1

{"name":"prop1","description":"blah","secure":false,"value":"value1"}

With PUT:

PUT /property/propSheet/applications&2e645851-31cb-45e8-9e26-732631e90872&environments&9d815997-b721-4aaf-9501-5fbf0474f679&propSheet.-1/propValues HTTP/1.1
Content-Type: application/x-www-form-urlencoded
User-Agent: HTTPClient/1.0 (2.3.3, ruby 2.0.0 (2013-06-27))
Accept: /
Date: Wed, 24 Jul 2013 21:19:30 GMT
Content-Length: 69
Host: host1

{"name":"prop1","description":"blah","secure":false,"value":"value1"}

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.