hyperquest 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 84e1f1d4d8832534efa9ad0c13c85beda3283f91
4
+ data.tar.gz: d695b4dd30b7db44ab381342273707166b79be1b
5
+ SHA512:
6
+ metadata.gz: 3a7f6b23f300be6dc65b27dac9cf2718c84d26f2210d513c401d2ec24e11a52ef7f9594ea8d5bbd45bda4678f9daae1fcbe5dd8cf2a85bf67258c7f3d96d86c2
7
+ data.tar.gz: 989f0afd8adf03a94a14f8929dffea91c3137f58fa46be7e40478ad3e47c5d87565a0094fe4d990c06431e49ac4ef31660d8e89d5c25ac9914df01a13bc4f57a
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ hyperquest.h
11
+ hyperquest.so
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
4
+ - 2.2.2
5
+ - 2.2.3
@@ -0,0 +1,2 @@
1
+ --markup-provider=redcarpet
2
+ --markup=markdown
@@ -0,0 +1,3 @@
1
+ ### 0.1.1 / 2015-09-05
2
+
3
+ Changed return string to CString (instead of GoString) fixing [#1](https://github.com/berfarah/hyperquest/issues/1)
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hyperquest.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem "rspec"
8
+ gem "simplecov", "~> 0.10", :require => false
9
+ gem "redcarpet"
10
+ end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Bernardo Farah
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,60 @@
1
+ # Hyperquest
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'hyperquest'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install hyperquest
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ require "hyperquest"
23
+
24
+ h = Hyperquest.get([url1, url2, url3])
25
+ # => Hash<url1 => Response, url2 => Response, url3 => Response>
26
+
27
+ h = Hyperquest.head([url1, url2, url3])
28
+ # => Hash<url1 => Response, url2 => Response, url3 => Response>
29
+
30
+ h[url1].uri
31
+ # => "http://example.com"
32
+ h[url1].content_length
33
+ # => 2435
34
+ h[url1].content_type
35
+ # => "text/html; charset UTF-8"
36
+ h[url1].body
37
+ # => "<HTML..."
38
+ h[url1].status
39
+ # => 200
40
+ h[url1].error
41
+ # => ""
42
+ h[url1].success?
43
+ # => true
44
+ h[url1].failed?
45
+ # => false
46
+ ```
47
+
48
+ ## Development
49
+
50
+ This gem is powered by [Go 1.5](https://golang.org/dl/)'s functionality of creating shared C libraries.
51
+
52
+ If you're on a mac, you can also install Go with [homebrew](http://brew.sh): `brew install go`. Please remember to `bundle` first!
53
+
54
+ ## Contributing
55
+
56
+ 1. Fork it ( https://github.com/berfarah/hyperquest/fork )
57
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
58
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
59
+ 4. Push to the branch (`git push origin my-new-feature`)
60
+ 5. Create a new Pull Request
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :xbuild do
4
+ # [:darwin, :linux].each do |os|
5
+ # sh "GOOS=#{os} GOARCH=amd64 go build -buildmode=c-shared -o ext/hyperquest-#{os}X86_64.so ext/hyperquest.go"
6
+ # end
7
+ sh "go build -buildmode=c-shared -o ext/hyperquest.so ext/hyperquest.go"
8
+ end
9
+
10
+ task :bench do
11
+ ruby "-Ilib examples/bench.rb"
12
+ end
@@ -0,0 +1,34 @@
1
+ require "hyperquest"
2
+ require "benchmark"
3
+
4
+ urls = %w(
5
+ http://google.com
6
+ http://bernardo.me
7
+ http://ruby-lang.org
8
+ http://golang.org
9
+ http://news.ycombinator.com
10
+ http://atom.io
11
+ http://sublimetext.com
12
+ http://kapeli.com/dash
13
+ http://github.com
14
+ )
15
+
16
+ Benchmark.bmbm do |r|
17
+ [:head, :get].each do |m|
18
+ r.report("1 request") do
19
+ Hyperquest.public_send(m, urls.shuffle.take(1))
20
+ end
21
+
22
+ r.report("3 request") do
23
+ Hyperquest.public_send(m, urls.shuffle.take(3))
24
+ end
25
+
26
+ r.report("5 request") do
27
+ Hyperquest.public_send(m, urls.shuffle.take(5))
28
+ end
29
+
30
+ r.report("9 request") do
31
+ Hyperquest.public_send(m, urls.shuffle.take(9))
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ require "hyperquest"
2
+
3
+ h = Hyperquest.get([url1, url2, url3])
4
+ # => Hash<url1 => Response, url2 => Response, url3 => Response>
5
+
6
+ h = Hyperquest.head([url1, url2, url3])
7
+ # => Hash<url1 => Response, url2 => Response, url3 => Response>
8
+
9
+ h[url1].uri
10
+ # => "http://example.com"
11
+ h[url1].content_length
12
+ # => 2435
13
+ h[url1].content_type
14
+ # => "text/html; charset UTF-8"
15
+ h[url1].body
16
+ # => "<HTML..."
17
+ h[url1].status
18
+ # => 200
19
+ h[url1].error
20
+ # => ""
21
+ h[url1].success?
22
+ # => true
23
+ h[url1].failed?
24
+ # => false
@@ -0,0 +1,18 @@
1
+ check := $(shell go version)
2
+ build:
3
+ ifeq ($(OS),Windows_NT)
4
+ shell echo "Windows is currently not supported"
5
+ shell exit /b 1
6
+ else
7
+ ifneq (,$(findstring go1.5,$(check)))
8
+ @echo Running go 1.5
9
+ go build -buildmode=c-shared -o hyperquest.so hyperquest.go
10
+ else
11
+ @echo Can't compile natively, instead downloading binary from github.
12
+ curl -L https://github.com/berfarah/hyperquest/releases/download/1.0.0/hyperquest-`uname -s`-`uname -m`.tar.gz | tar zx
13
+ endif
14
+ endif
15
+
16
+ # These are required to install successfully
17
+ clean:
18
+ install:
@@ -0,0 +1,3 @@
1
+ # Run our makefile since we're not using mkmf
2
+ puts "Installing extension..."
3
+ system("make")
@@ -0,0 +1,81 @@
1
+ package main
2
+
3
+ import (
4
+ "C"
5
+ "encoding/json"
6
+ "io/ioutil"
7
+ "net/http"
8
+ )
9
+
10
+ type Response struct {
11
+ URI string `json:"uri"`
12
+ ContentType string `json:"content_type"`
13
+ ContentLength int64 `json:"content_length"`
14
+ Body string `json:"body"`
15
+ Status int `json:"status"`
16
+ Err string `json:"error"`
17
+ }
18
+
19
+ func request(data *C.char, req func(string) (*http.Response, error)) *C.char {
20
+ uris := []string{}
21
+ err := json.Unmarshal([]byte(C.GoString(data)), &uris)
22
+ if err != nil {
23
+ return C.CString(err.Error())
24
+ }
25
+
26
+ if len(uris) == 0 || (len(uris) == 1 && uris[0] == "") {
27
+ return C.CString("[]")
28
+ }
29
+
30
+ c := make(chan *Response)
31
+ for _, uri := range uris {
32
+ go func(u string) {
33
+ resp, err := req(u)
34
+ c <- readRequest(u, resp, err)
35
+ }(uri)
36
+ }
37
+
38
+ result := []*Response{}
39
+ for i := 0; i < len(uris); i++ {
40
+ result = append(result, <-c)
41
+ }
42
+
43
+ b, err := json.Marshal(result)
44
+ if err != nil {
45
+ return C.CString("{}")
46
+ }
47
+
48
+ return C.CString(string(b))
49
+ }
50
+
51
+ func readRequest(uri string, r *http.Response, err error) *Response {
52
+ if err != nil {
53
+ return &Response{URI: uri, Status: r.StatusCode, Err: err.Error()}
54
+ }
55
+ defer r.Body.Close()
56
+
57
+ body, err := ioutil.ReadAll(r.Body)
58
+ if err != nil {
59
+ return &Response{URI: uri, Status: r.StatusCode, Err: err.Error()}
60
+ }
61
+
62
+ return &Response{
63
+ URI: uri,
64
+ ContentType: r.Header.Get("Content-Type"),
65
+ ContentLength: r.ContentLength,
66
+ Body: string(body),
67
+ Status: r.StatusCode,
68
+ }
69
+ }
70
+
71
+ //export get
72
+ func get(data *C.char) *C.char {
73
+ return request(data, http.Get)
74
+ }
75
+
76
+ //export head
77
+ func head(data *C.char) *C.char {
78
+ return request(data, http.Head)
79
+ }
80
+
81
+ func main() {}
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "hyperquest"
5
+ spec.version = "1.0.2"
6
+ spec.authors = ["Bernardo Farah"]
7
+ spec.email = ["ber@bernardo.me"]
8
+
9
+ spec.summary = "A gem for asynchronous get requests, written in Go"
10
+ spec.description = "Hyperquest allows you to do an unlimited amount of "\
11
+ "HEAD or GET requests via a native extension."
12
+ spec.homepage = "https://github.com/berfarah/hyperquest"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
16
+ spec.require_paths = ["lib"]
17
+ spec.extensions = %w(ext/extconf.rb)
18
+
19
+ spec.add_dependency "ffi", "~> 1.9"
20
+ spec.add_development_dependency "yard", "~> 0.8"
21
+ spec.add_development_dependency "bundler", "~> 1.9"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ end
@@ -0,0 +1,22 @@
1
+ require "ffi"
2
+ require "json"
3
+ require "hyperquest/request"
4
+
5
+ # {Hyperquest} is a library for doing asynchronous GET and HEAD requests.
6
+ module Hyperquest
7
+ # Asynchronous get requests
8
+ #
9
+ # @param [Array[String]] uri URI to be requested
10
+ # @return [Hash<String => Response>] See {Response}
11
+ def self.get(uri)
12
+ Request.open(:get, uri)
13
+ end
14
+
15
+ # Asynchronous head request
16
+ #
17
+ # @param [Array[String]] uri URI to be requested
18
+ # @return [Hash<String => Response>] See {Response}
19
+ def self.head(uri)
20
+ Request.open(:head, uri)
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ require "json"
2
+ require "hyperquest/response"
3
+
4
+ module Hyperquest
5
+ # Dispatcher to Golang
6
+ #
7
+ # @api private
8
+ module Request
9
+ extend FFI::Library
10
+
11
+ ffi_lib File.expand_path("../../../ext/hyperquest.so", __FILE__)
12
+
13
+ # Does asynchronous get requests via a go extension
14
+ attach_function :get, [:string], :string
15
+ attach_function :head, [:string], :string
16
+
17
+ # Open a type of request via our extension
18
+ #
19
+ # @param [Symbol] type Valid options are get and head
20
+ # @param [Array<String>] uri Uri to be requested
21
+ # @return [Array<Response>] {Response}
22
+ def self.open(type, uri)
23
+ response = public_send(type, Array(uri).to_json)
24
+ JSON.parse(response).each_with_object({}) do |e, hash|
25
+ hash[e["uri"]] = Response.new(e)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,48 @@
1
+ require "ostruct"
2
+ require "forwardable"
3
+
4
+ module Hyperquest
5
+ # Hyperquest::Response is a wrapper for responses from hyperquest.go
6
+ class Response < OpenStruct
7
+ extend Forwardable
8
+
9
+ # Instantiated by {Request} - see {Request.open}
10
+ #
11
+ # @api private
12
+ # @param [Hash] hash Parsed JSON
13
+ # @return [Response]
14
+ def initialize(hash)
15
+ @response = OpenStruct.new(hash).freeze
16
+ end
17
+
18
+ # @!group Attributes
19
+ # @!attribute [r] uri
20
+ # @return [String] Request url
21
+ # @!attribute [r] content_length
22
+ # @return [Fixnum]
23
+ # @!attribute [r] content_type
24
+ # @return [String]
25
+ # @!attribute [r] body
26
+ # @return [String]
27
+ # @!attribute [r] status
28
+ # @return [Fixnum]
29
+ # @!attribute [r] error
30
+ # @return [String]
31
+ def_delegators :@response,
32
+ :uri, :content_length, :content_type,
33
+ :body, :status, :error
34
+
35
+ # Returns true if error is empty
36
+ # @return [Boolean]
37
+ def success?
38
+ error.empty?
39
+ end
40
+
41
+ # Returns true if error is not empty
42
+ # @return [Boolean]
43
+ def failed?
44
+ !success?
45
+ end
46
+ # @!endgroup
47
+ end
48
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hyperquest
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Bernardo Farah
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: yard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ description: Hyperquest allows you to do an unlimited amount of HEAD or GET requests
70
+ via a native extension.
71
+ email:
72
+ - ber@bernardo.me
73
+ executables: []
74
+ extensions:
75
+ - ext/extconf.rb
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - ".rspec"
80
+ - ".travis.yml"
81
+ - ".yardopts"
82
+ - CHANGELOG.md
83
+ - Gemfile
84
+ - LICENSE.txt
85
+ - README.md
86
+ - Rakefile
87
+ - examples/bench.rb
88
+ - examples/usage.rb
89
+ - ext/Makefile
90
+ - ext/extconf.rb
91
+ - ext/hyperquest.go
92
+ - hyperquest.gemspec
93
+ - lib/hyperquest.rb
94
+ - lib/hyperquest/request.rb
95
+ - lib/hyperquest/response.rb
96
+ homepage: https://github.com/berfarah/hyperquest
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.4.5.1
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: A gem for asynchronous get requests, written in Go
120
+ test_files: []
121
+ has_rdoc: