gohttp 0.1.0

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: 6970bde6a9b5abb0c5dba6d1d24dd8d45e6d5f03
4
+ data.tar.gz: a49d93842ba8fbb32e5daf62c2cadfc406013d24
5
+ SHA512:
6
+ metadata.gz: 76290ca49818def17d3d107273b84811511d668539c3cecd01a79250d39ac50e52ad421ea6721177438c07936b7376024422950998e3cc45e44e6df22b181387
7
+ data.tar.gz: 37f5738e18ce5210bcca7afc3a13860138eb23021178cb5783537b2969d11bc53f07da103bc9710f73f6c4019510c8c5a3d679fa07a49409026f498334418828
@@ -0,0 +1,17 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.swp
13
+ *.o
14
+ *.a
15
+ mkmf.log
16
+ gohttp.h
17
+ gohttp.so
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (C) 2015 NARUSE, Yui. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
@@ -0,0 +1,35 @@
1
+ # Gohttp
2
+
3
+ A demo to implement a extension library with Go.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'gohttp'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install gohttp
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+ require 'gohttp'
25
+ r = Gohttp.get('https://example.com/index.html')
26
+ puts r.body.read
27
+ ```
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it ( https://github.com/nurse/gohttp/fork )
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create a new Pull Request
@@ -0,0 +1,18 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+ require 'rspec/core/rake_task'
4
+ require 'rake/extensiontask'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+ task :default => [:compile, :spec]
8
+
9
+ spec = eval File.read('gohttp.gemspec')
10
+ Rake::ExtensionTask.new('gohttp', spec) do |ext|
11
+ ext.ext_dir = 'ext/gohttp'
12
+ ext.lib_dir = File.join(*['lib', 'gohttp', ENV['FAT_DIR']].compact)
13
+ ext.source_pattern = "*.{c,cpp,go}"
14
+ end
15
+
16
+ RSpec::Core::RakeTask.new :spec do |spec|
17
+ spec.pattern = 'spec/**/*_spec.rb'
18
+ end
@@ -0,0 +1,18 @@
1
+ require 'mkmf'
2
+ find_executable('go')
3
+ $objs = []
4
+ def $objs.empty?; false ;end
5
+ create_makefile("gohttp/gohttp")
6
+ case `#{CONFIG['CC']} --version`
7
+ when /Free Software Foundation/
8
+ ldflags = '-Wl,--unresolved-symbols=ignore-all'
9
+ when /clang/
10
+ ldflags = '-undefined dynamic_lookup'
11
+ end
12
+ File.open('Makefile', 'a') do |f|
13
+ f.write <<eom.gsub(/^ {8}/, "\t")
14
+ $(DLLIB): Makefile $(srcdir)/gohttp.go $(srcdir)/wrapper.go
15
+ CGO_CFLAGS='$(INCFLAGS)' CGO_LDFLAGS='#{ldflags}' \
16
+ go build -p 4 -buildmode=c-shared -o $(DLLIB) $(srcdir)/gohttp.go $(srcdir)/wrapper.go
17
+ eom
18
+ end
@@ -0,0 +1,362 @@
1
+ package main
2
+
3
+ /*
4
+ #include <ruby/ruby.h>
5
+
6
+ VALUE NewGoStruct(VALUE klass, void *p);
7
+ void *GetGoStruct(VALUE obj);
8
+
9
+ VALUE gohttp_hello(VALUE);
10
+ VALUE gohttpGet(VALUE,VALUE);
11
+ VALUE gohttpHead(VALUE,VALUE);
12
+ int hash_of_ary_of_str2values_i(VALUE,VALUE,VALUE);
13
+ VALUE gohttpPostForm(VALUE,VALUE,VALUE);
14
+ VALUE gohttp_get_url(VALUE,VALUE);
15
+ VALUE gourlQueryEscape(VALUE,VALUE);
16
+ VALUE gourlQueryUnescape(VALUE,VALUE);
17
+
18
+ VALUE goio_to_s(VALUE);
19
+ VALUE goioRead(VALUE);
20
+ VALUE goioClose(VALUE);
21
+
22
+ VALUE reqMethod(VALUE);
23
+ VALUE reqURL(VALUE);
24
+ VALUE reqProto(VALUE);
25
+ VALUE reqHeader(VALUE);
26
+ VALUE reqBody(VALUE);
27
+ VALUE reqContentLength(VALUE);
28
+ VALUE reqTransferEncoding(VALUE);
29
+ VALUE reqHost(VALUE);
30
+ VALUE reqForm(VALUE);
31
+ VALUE reqForm(VALUE);
32
+ VALUE reqForm(VALUE);
33
+ VALUE reqForm(VALUE);
34
+ VALUE reqRemoteAddr(VALUE);
35
+ VALUE reqRequestURI(VALUE);
36
+
37
+ VALUE respContentLength(VALUE);
38
+ VALUE respStatus(VALUE);
39
+ VALUE respStatusCode(VALUE);
40
+ VALUE respProto(VALUE);
41
+ VALUE respTransferEncoding(VALUE);
42
+ VALUE respHeader(VALUE);
43
+ VALUE respBody(VALUE);
44
+ VALUE respRequest(VALUE);
45
+ */
46
+ import "C"
47
+
48
+ import "fmt"
49
+ import "io"
50
+ import "io/ioutil"
51
+ import "net/http"
52
+ import "net/url"
53
+ import "reflect"
54
+ import "unsafe"
55
+
56
+ func main() {
57
+ }
58
+
59
+ var rb_cGoIO C.VALUE
60
+ var rb_cGohttp C.VALUE
61
+ var rb_cGourl C.VALUE
62
+ var rb_cRequest C.VALUE
63
+ var rb_cResponse C.VALUE
64
+
65
+ //export goobj_retain
66
+ func goobj_retain(obj unsafe.Pointer) {
67
+ objects[obj] = true
68
+ }
69
+
70
+ //export goobj_free
71
+ func goobj_free(obj unsafe.Pointer) {
72
+ delete(objects, obj)
73
+ }
74
+
75
+ func goioNew(klass C.VALUE, r interface{}) C.VALUE {
76
+ v := reflect.ValueOf(r)
77
+ return C.NewGoStruct(klass, unsafe.Pointer(&v))
78
+ }
79
+
80
+ //export goio_to_s
81
+ func goio_to_s(self C.VALUE) C.VALUE {
82
+ v := (*reflect.Value)(C.GetGoStruct(self))
83
+ switch v.Kind() {
84
+ case reflect.Struct:
85
+ return RbString(fmt.Sprintf("#<GoIO:%s>", v.Type().String()))
86
+ case reflect.Chan, reflect.Map, reflect.Ptr, reflect.UnsafePointer:
87
+ return RbString(fmt.Sprintf("#<GoIO:%s:0x%X>", v.Type().String(), v.Pointer()))
88
+ default:
89
+ return RbString(fmt.Sprintf("#<GoIO:%s>", v.Type().String()))
90
+ }
91
+ }
92
+
93
+ //export goioRead
94
+ func goioRead(self C.VALUE) C.VALUE {
95
+ v := (*reflect.Value)(C.GetGoStruct(self))
96
+ r := v.Interface().(io.Reader)
97
+ body, err := ioutil.ReadAll(r)
98
+ if err != nil {
99
+ rb_raise(C.rb_eArgError, "'%s'", err)
100
+ }
101
+ return RbBytes(body)
102
+ }
103
+
104
+ //export goioClose
105
+ func goioClose(self C.VALUE) C.VALUE {
106
+ v := (*reflect.Value)(C.GetGoStruct(self))
107
+ if c, ok := v.Interface().(io.Closer); ok {
108
+ c.Close()
109
+ return C.Qtrue
110
+ }
111
+ return C.Qfalse
112
+ }
113
+
114
+ func reqNew(klass C.VALUE, r *http.Request) C.VALUE {
115
+ return C.NewGoStruct(klass, unsafe.Pointer(r))
116
+ }
117
+
118
+ //export reqMethod
119
+ func reqMethod(self C.VALUE) C.VALUE {
120
+ req := (*http.Request)(C.GetGoStruct(self))
121
+ return RbString(req.Method)
122
+ }
123
+
124
+ //export reqProto
125
+ func reqProto(self C.VALUE) C.VALUE {
126
+ req := (*http.Request)(C.GetGoStruct(self))
127
+ return RbString(req.Proto)
128
+ }
129
+
130
+ //export reqHeader
131
+ func reqHeader(self C.VALUE) C.VALUE {
132
+ req := (*http.Request)(C.GetGoStruct(self))
133
+ h := C.rb_hash_new()
134
+ for key, value := range req.Header {
135
+ C.rb_hash_aset(h, RbString(key), StrSlice2RbArray(value))
136
+ }
137
+ return h
138
+ }
139
+
140
+ //export reqBody
141
+ func reqBody(self C.VALUE) C.VALUE {
142
+ req := (*http.Request)(C.GetGoStruct(self))
143
+ if req.Body == nil {
144
+ return C.Qnil
145
+ }
146
+ return goioNew(rb_cGoIO, req.Body)
147
+ }
148
+
149
+ //export reqContentLength
150
+ func reqContentLength(self C.VALUE) C.VALUE {
151
+ req := (*http.Request)(C.GetGoStruct(self))
152
+ return INT64toNUM(req.ContentLength)
153
+ }
154
+
155
+ //export reqTransferEncoding
156
+ func reqTransferEncoding(self C.VALUE) C.VALUE {
157
+ req := (*http.Request)(C.GetGoStruct(self))
158
+ return StrSlice2RbArray(req.TransferEncoding)
159
+ }
160
+
161
+ //export reqHost
162
+ func reqHost(self C.VALUE) C.VALUE {
163
+ req := (*http.Request)(C.GetGoStruct(self))
164
+ return RbString(req.Host)
165
+ }
166
+
167
+ //export reqRemoteAddr
168
+ func reqRemoteAddr(self C.VALUE) C.VALUE {
169
+ req := (*http.Request)(C.GetGoStruct(self))
170
+ return RbString(req.RemoteAddr)
171
+ }
172
+
173
+ //export reqRequestURI
174
+ func reqRequestURI(self C.VALUE) C.VALUE {
175
+ req := (*http.Request)(C.GetGoStruct(self))
176
+ return RbString(req.RequestURI)
177
+ }
178
+
179
+ func respNew(klass C.VALUE, r *http.Response) C.VALUE {
180
+ return C.NewGoStruct(klass, unsafe.Pointer(r))
181
+ }
182
+
183
+ //export respContentLength
184
+ func respContentLength(self C.VALUE) C.VALUE {
185
+ resp := (*http.Response)(C.GetGoStruct(self))
186
+ return INT64toNUM(resp.ContentLength)
187
+ }
188
+
189
+ //export respHeader
190
+ func respHeader(self C.VALUE) C.VALUE {
191
+ resp := (*http.Response)(C.GetGoStruct(self))
192
+ h := C.rb_hash_new()
193
+ for key, value := range resp.Header {
194
+ C.rb_hash_aset(h, RbString(key), StrSlice2RbArray(value))
195
+ }
196
+ return h
197
+ }
198
+
199
+ //export respStatus
200
+ func respStatus(self C.VALUE) C.VALUE {
201
+ resp := (*http.Response)(C.GetGoStruct(self))
202
+ return RbString(resp.Status)
203
+ }
204
+
205
+ //export respStatusCode
206
+ func respStatusCode(self C.VALUE) C.VALUE {
207
+ resp := (*http.Response)(C.GetGoStruct(self))
208
+ return INT2NUM(resp.StatusCode)
209
+ }
210
+
211
+ //export respProto
212
+ func respProto(self C.VALUE) C.VALUE {
213
+ resp := (*http.Response)(C.GetGoStruct(self))
214
+ return RbString(resp.Proto)
215
+ }
216
+
217
+ //export respTransferEncoding
218
+ func respTransferEncoding(self C.VALUE) C.VALUE {
219
+ resp := (*http.Response)(C.GetGoStruct(self))
220
+ return StrSlice2RbArray(resp.TransferEncoding)
221
+ }
222
+
223
+ //export respBody
224
+ func respBody(self C.VALUE) C.VALUE {
225
+ resp := (*http.Response)(C.GetGoStruct(self))
226
+ if resp.Body == nil {
227
+ return C.Qnil
228
+ }
229
+ return goioNew(rb_cGoIO, resp.Body)
230
+ }
231
+
232
+ //export respRequest
233
+ func respRequest(self C.VALUE) C.VALUE {
234
+ resp := (*http.Response)(C.GetGoStruct(self))
235
+ return reqNew(rb_cRequest, resp.Request)
236
+ }
237
+
238
+ //export gohttp_hello
239
+ func gohttp_hello(dummy C.VALUE) C.VALUE {
240
+ fmt.Printf("hello, world\n")
241
+ return C.Qnil
242
+ }
243
+
244
+ //export gohttpGet
245
+ func gohttpGet(dummy C.VALUE, urlstr C.VALUE) C.VALUE {
246
+ str := RbGoString(urlstr)
247
+ resp, err := http.Get(str)
248
+ if err != nil {
249
+ rb_raise(C.rb_eArgError, "'%s'", err)
250
+ }
251
+ return respNew(rb_cResponse, resp)
252
+ }
253
+
254
+ //export gohttpHead
255
+ func gohttpHead(dummy C.VALUE, urlstr C.VALUE) C.VALUE {
256
+ str := RbGoString(urlstr)
257
+ resp, err := http.Head(str)
258
+ if err != nil {
259
+ rb_raise(C.rb_eArgError, "'%s'", err)
260
+ }
261
+ return respNew(rb_cResponse, resp)
262
+ }
263
+
264
+ //export hash_of_ary_of_str2values_i
265
+ func hash_of_ary_of_str2values_i(key C.VALUE, ary C.VALUE, arg C.VALUE) C.int {
266
+ values := (*url.Values)(unsafe.Pointer(uintptr(arg)))
267
+ values.Add(RbGoString(key), RbGoString(ary))
268
+ return C.ST_CONTINUE
269
+ }
270
+
271
+ //export gohttpPostForm
272
+ func gohttpPostForm(dummy C.VALUE, urlstr C.VALUE, data C.VALUE) C.VALUE {
273
+ str := RbGoString(urlstr)
274
+ val := url.Values{}
275
+ C.rb_hash_foreach(data, (*[0]byte)(C.hash_of_ary_of_str2values_i), C.VALUE(uintptr(unsafe.Pointer(&val))))
276
+ resp, err := http.PostForm(str, val)
277
+ if err != nil {
278
+ rb_raise(C.rb_eArgError, "'%s'", err)
279
+ }
280
+ return respNew(rb_cResponse, resp)
281
+ }
282
+
283
+ //export gohttp_get_url
284
+ func gohttp_get_url(dummy C.VALUE, urlstr C.VALUE) C.VALUE {
285
+ u, err := url.Parse(RbGoString(urlstr))
286
+ if err != nil {
287
+ return C.Qnil
288
+ }
289
+ return RbString(u.String())
290
+ }
291
+
292
+ //export gourlQueryEscape
293
+ func gourlQueryEscape(dummy C.VALUE, s C.VALUE) C.VALUE {
294
+ return RbString(url.QueryEscape(RbGoString(s)))
295
+ }
296
+
297
+ //export gourlQueryUnescape
298
+ func gourlQueryUnescape(dummy C.VALUE, s C.VALUE) C.VALUE {
299
+ src := RbGoString(s)
300
+ str, err := url.QueryUnescape(src)
301
+ if err != nil {
302
+ rb_raise(C.rb_eArgError, "'%s' is not valid pct-encoded", src)
303
+ }
304
+ return RbString(str)
305
+ }
306
+
307
+ //export Init_gohttp
308
+ func Init_gohttp() {
309
+ sNew := "new"
310
+ str_new := (*C.char)(unsafe.Pointer(&(*(*[]byte)(unsafe.Pointer(&sNew)))[0]))
311
+
312
+ rb_cGoIO = rb_define_class("GoIO", C.rb_cIO)
313
+ C.rb_undef_alloc_func(rb_cGoIO)
314
+ C.rb_undef_method(C.rb_class_of(rb_cGoIO), str_new)
315
+ rb_define_method(rb_cGoIO, "to_s", C.goio_to_s, 0)
316
+ rb_define_method(rb_cGoIO, "inspect", C.goio_to_s, 0)
317
+ rb_define_method(rb_cGoIO, "read", C.goioRead, 0)
318
+ rb_define_method(rb_cGoIO, "close", C.goioClose, 0)
319
+
320
+ rb_cRequest = rb_define_class("Request", C.rb_cObject)
321
+ C.rb_undef_alloc_func(rb_cRequest)
322
+ C.rb_undef_method(C.rb_class_of(rb_cRequest), str_new)
323
+ rb_define_method(rb_cRequest, "method", C.reqMethod, 0)
324
+ //rb_define_method(rb_cRequest, "url", C.reqURL, 0)
325
+ rb_define_method(rb_cRequest, "proto", C.reqProto, 0)
326
+ rb_define_method(rb_cRequest, "header", C.reqHeader, 0)
327
+ rb_define_method(rb_cRequest, "body", C.reqBody, 0)
328
+ rb_define_method(rb_cRequest, "content_length", C.reqContentLength, 0)
329
+ rb_define_method(rb_cRequest, "transfer_encoding", C.reqTransferEncoding, 0)
330
+ rb_define_method(rb_cRequest, "host", C.reqHost, 0)
331
+ //rb_define_method(rb_cRequest, "form", C.reqForm, 0)
332
+ //rb_define_method(rb_cRequest, "post_form", C.reqForm, 0)
333
+ //rb_define_method(rb_cRequest, "multipart_form", C.reqForm, 0)
334
+ //rb_define_method(rb_cRequest, "trailer", C.reqForm, 0)
335
+ rb_define_method(rb_cRequest, "remote_addr", C.reqRemoteAddr, 0)
336
+ rb_define_method(rb_cRequest, "request_uri", C.reqRequestURI, 0)
337
+
338
+ rb_cResponse = rb_define_class("Response", C.rb_cObject)
339
+ C.rb_undef_alloc_func(rb_cResponse)
340
+ C.rb_undef_method(C.rb_class_of(rb_cResponse), str_new)
341
+ rb_define_method(rb_cResponse, "size", C.respContentLength, 0)
342
+ rb_define_method(rb_cResponse, "status", C.respStatus, 0)
343
+ rb_define_method(rb_cResponse, "status_code", C.respStatusCode, 0)
344
+ rb_define_method(rb_cResponse, "proto", C.respProto, 0)
345
+ rb_define_method(rb_cResponse, "transfer_encoding", C.respTransferEncoding, 0)
346
+ rb_define_method(rb_cResponse, "header", C.respHeader, 0)
347
+ rb_define_method(rb_cResponse, "body", C.respBody, 0)
348
+ rb_define_method(rb_cResponse, "request", C.respRequest, 0)
349
+
350
+ rb_cGohttp = rb_define_class("Gohttp", C.rb_cObject)
351
+ rb_define_singleton_method(rb_cGohttp, "hello", C.gohttp_hello, 0)
352
+ rb_define_singleton_method(rb_cGohttp, "get", C.gohttpGet, 1)
353
+ rb_define_singleton_method(rb_cGohttp, "head", C.gohttpHead, 1)
354
+ //rb_define_singleton_method(rb_cGohttp, "post", C.gohttpPost, 1)
355
+ rb_define_singleton_method(rb_cGohttp, "post_form", C.gohttpPostForm, 2)
356
+ //rb_define_method(rb_cGohttp, "initialize", C.gohttp_initialize, 1)
357
+ rb_define_method(rb_cGohttp, "get_url", C.gohttp_get_url, 1)
358
+
359
+ rb_cGourl = rb_define_class("Gourl", C.rb_cObject)
360
+ rb_define_singleton_method(rb_cGourl, "query_escape", C.gourlQueryEscape, 1)
361
+ rb_define_singleton_method(rb_cGourl, "query_unescape", C.gourlQueryUnescape, 1)
362
+ }
@@ -0,0 +1,105 @@
1
+ package main
2
+
3
+ /*
4
+ #include <ruby/ruby.h>
5
+
6
+ const char *
7
+ rstring_ptr(VALUE str) {
8
+ return RSTRING_PTR(str);
9
+ }
10
+ int
11
+ rstring_len(VALUE str) {
12
+ return RSTRING_LENINT(str);
13
+ }
14
+ void
15
+ rb_raise2(VALUE exc, const char *str) {
16
+ rb_raise(exc, "%s", str);
17
+ }
18
+
19
+ void goobj_retain(void *);
20
+ void goobj_free(void *);
21
+
22
+ static const rb_data_type_t go_type = {
23
+ "GoStruct",
24
+ {NULL, goobj_free, NULL},
25
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
26
+ };
27
+
28
+ VALUE
29
+ NewGoStruct(VALUE klass, void *p)
30
+ {
31
+ goobj_retain(p);
32
+ return TypedData_Wrap_Struct((klass), &go_type, p);
33
+ }
34
+
35
+ void *
36
+ GetGoStruct(VALUE obj)
37
+ {
38
+ void *val;
39
+ return TypedData_Get_Struct((obj), void *, &go_type, (val));
40
+ }
41
+ */
42
+ import "C"
43
+ import "unsafe"
44
+ import "fmt"
45
+
46
+ var objects = make(map[interface{}]bool)
47
+
48
+ func rb_define_method(klass C.VALUE, name string, fun unsafe.Pointer, args int) {
49
+ cname := (*C.char)(unsafe.Pointer(&(*(*[]byte)(unsafe.Pointer(&name)))[0]))
50
+ C.rb_define_method(klass, cname, (*[0]byte)(fun), C.int(args))
51
+ }
52
+
53
+ func rb_define_singleton_method(klass C.VALUE, name string, fun unsafe.Pointer, args int) {
54
+ cname := (*C.char)(unsafe.Pointer(&(*(*[]byte)(unsafe.Pointer(&name)))[0]))
55
+ C.rb_define_singleton_method(klass, cname, (*[0]byte)(fun), C.int(args))
56
+ }
57
+
58
+ func RbGoString(str C.VALUE) string {
59
+ C.rb_string_value(&str)
60
+ return C.GoStringN(C.rstring_ptr(str), C.rstring_len(str))
61
+ }
62
+
63
+ func RbBytes(bytes []byte) C.VALUE {
64
+ if len(bytes) == 0 {
65
+ return C.rb_str_new(nil, C.long(0))
66
+ }
67
+ cstr := (*C.char)(unsafe.Pointer(&bytes[0]))
68
+ return C.rb_str_new(cstr, C.long(len(bytes)))
69
+ }
70
+
71
+ func RbString(str string) C.VALUE {
72
+ if len(str) == 0 {
73
+ return C.rb_utf8_str_new(nil, C.long(0))
74
+ }
75
+ cstr := (*C.char)(unsafe.Pointer(&(*(*[]byte)(unsafe.Pointer(&str)))[0]))
76
+ return C.rb_utf8_str_new(cstr, C.long(len(str)))
77
+ }
78
+
79
+ func rb_define_class(name string, parent C.VALUE) C.VALUE {
80
+ cname := (*C.char)(unsafe.Pointer(&(*(*[]byte)(unsafe.Pointer(&name)))[0]))
81
+ v := C.rb_define_class(cname, parent)
82
+ return v
83
+ }
84
+
85
+ func rb_raise(exc C.VALUE, format string, a ...interface{}) {
86
+ str := fmt.Sprintf(format, a...)
87
+ cstr := (*C.char)(unsafe.Pointer(&(*(*[]byte)(unsafe.Pointer(&str)))[0]))
88
+ C.rb_raise2(exc, cstr)
89
+ }
90
+
91
+ func INT2NUM(n int) C.VALUE {
92
+ return C.rb_int2inum(C.long(n))
93
+ }
94
+
95
+ func INT64toNUM(n int64) C.VALUE {
96
+ return C.rb_ll2inum(C.longlong(n))
97
+ }
98
+
99
+ func StrSlice2RbArray(slice []string) C.VALUE {
100
+ ary := C.rb_ary_new_capa(C.long(len(slice)))
101
+ for _, val := range slice {
102
+ C.rb_ary_push(ary, RbString(val))
103
+ }
104
+ return ary
105
+ }
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gohttp/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gohttp"
8
+ spec.version = Strptime::VERSION
9
+ spec.authors = ["NARUSE, Yui"]
10
+ spec.email = ["naruse@airemix.jp"]
11
+
12
+ spec.summary = %q{an http library with go.}
13
+ spec.description = %q{an http library with go.}
14
+ spec.homepage = "https://github.com/nurse/gohttp"
15
+ spec.license = "BSD-2-Clause"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+ spec.extensions = ["ext/gohttp/extconf.rb"]
22
+ spec.required_ruby_version = '~> 2.0'
23
+
24
+ spec.add_development_dependency "bundler"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rake-compiler"
27
+ spec.add_development_dependency "rspec"
28
+ spec.add_development_dependency 'yard'
29
+ end
@@ -0,0 +1,10 @@
1
+ require "gohttp/version"
2
+ begin
3
+ require "gohttp/#{RUBY_VERSION[/\d+\.\d+/]}/gohttp"
4
+ rescue LoadError
5
+ require "gohttp/gohttp"
6
+ end
7
+
8
+ class Gohttp
9
+ # Your code goes here...
10
+ end
@@ -0,0 +1,3 @@
1
+ class Strptime
2
+ VERSION = "0.1.0"
3
+ end
data/test.rb ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gohttp'
4
+ require 'minitest/autorun'
5
+
6
+ class TestGohttp < Minitest::Test
7
+ def test_hello
8
+ assert_output("hello, world\n") do
9
+ Gohttp.hello
10
+ end
11
+ end
12
+
13
+ def test_hello
14
+ o = Object.new
15
+ def o.to_str; "https://例え.テスト/ファイル.html"; end
16
+ g = Gohttp.new
17
+ assert_equal "https://%E4%BE%8B%E3%81%88.%E3%83%86%E3%82%B9%E3%83%88/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.html", g.get_url(o)
18
+ end
19
+
20
+ def test_get
21
+ r = Gohttp.get('https://example.com/index.html')
22
+ assert_kind_of Response, r
23
+ assert_equal '200 OK', r.status
24
+ assert_equal 200, r.status_code
25
+ assert_equal 'HTTP/1.1', r.proto
26
+ assert_equal 1270, r.size
27
+ assert_equal [], r.transfer_encoding
28
+ hdr = r.header
29
+ assert_kind_of Hash, hdr
30
+ assert_equal %w[max-age=604800], hdr["Cache-Control"]
31
+ assert_equal %w[text/html], hdr["Content-Type"]
32
+ b = r.body
33
+ assert_match /\A#<GoIO:\*http.bodyEOFSignal:0x\h+>/, b.to_s
34
+ assert_match /Example Domain/, b.read
35
+ assert_equal true, b.close
36
+ req = r.request
37
+ assert_equal 'GET', req.method
38
+ assert_equal 'HTTP/1.1', req.proto
39
+ assert_equal Hash[], req.header
40
+ assert_nil req.body
41
+ assert_equal 0, req.content_length
42
+ assert_equal [], req.transfer_encoding
43
+ assert_equal 'example.com', req.host
44
+ assert_equal '', req.remote_addr
45
+ assert_equal '', req.request_uri
46
+ end
47
+
48
+ def test_head
49
+ r = Gohttp.head('https://example.com/index.html')
50
+ assert_kind_of Response, r
51
+ assert_equal '200 OK', r.status
52
+ assert_equal 200, r.status_code
53
+ assert_equal 'HTTP/1.1', r.proto
54
+ assert_equal 1270, r.size
55
+ assert_equal [], r.transfer_encoding
56
+ hdr = r.header
57
+ assert_kind_of Hash, hdr
58
+ assert_equal %w[max-age=604800], hdr["Cache-Control"]
59
+ assert_equal %w[text/html], hdr["Content-Type"]
60
+ b = r.body
61
+ assert_match /\A#<GoIO:\*http.bodyEOFSignal>/, b.to_s
62
+ assert_match '', b.read
63
+ assert_equal true, b.close
64
+ req = r.request
65
+ assert_equal 'HEAD', req.method
66
+ assert_equal 'HTTP/1.1', req.proto
67
+ assert_equal Hash[], req.header
68
+ assert_nil req.body
69
+ assert_equal 0, req.content_length
70
+ assert_equal [], req.transfer_encoding
71
+ assert_equal 'example.com', req.host
72
+ assert_equal '', req.remote_addr
73
+ assert_equal '', req.request_uri
74
+ end
75
+
76
+ def test_head
77
+ r = Gohttp.post_form('http://nalsh.jp/env.cgi', {'foo' => 'bar'})
78
+ assert_kind_of Response, r
79
+ assert_equal '200 OK', r.status
80
+ assert_equal 200, r.status_code
81
+ assert_equal 'HTTP/1.1', r.proto
82
+ assert_equal -1, r.size
83
+ assert_equal %w[chunked], r.transfer_encoding
84
+ hdr = r.header
85
+ assert_kind_of Hash, hdr
86
+ assert_equal nil, hdr["Cache-Control"]
87
+ assert_equal %w[text/html], hdr["Content-Type"]
88
+ b = r.body
89
+ assert_match /\A#<GoIO:\*http.bodyEOFSignal:0x\h+>/, b.to_s
90
+ assert_match '', b.read
91
+ assert_equal true, b.close
92
+ req = r.request
93
+ assert_equal 'POST', req.method
94
+ assert_equal 'HTTP/1.1', req.proto
95
+ assert_equal Hash["Content-Type"=>["application/x-www-form-urlencoded"]], req.header
96
+ assert_match /\A#<GoIO:ioutil.nopCloser>\z/, req.body.to_s
97
+ assert_equal 7, req.content_length
98
+ assert_equal [], req.transfer_encoding
99
+ assert_equal 'nalsh.jp', req.host
100
+ assert_equal '', req.remote_addr
101
+ assert_equal '', req.request_uri
102
+ end
103
+ end
104
+
105
+ class TestGourl < Minitest::Test
106
+ def test_escape
107
+ assert_equal '%E3%81%82+%2B', Gourl.query_escape('あ +')
108
+ end
109
+
110
+ def test_escape
111
+ assert_equal 'あ ', Gourl.query_unescape('%E3%81%82%20+')
112
+ assert_raises(ArgumentError){ Gourl.query_unescape('%%81%82%20+') }
113
+ end
114
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gohttp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - NARUSE, Yui
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-11-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake-compiler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: an http library with go.
84
+ email:
85
+ - naruse@airemix.jp
86
+ executables: []
87
+ extensions:
88
+ - ext/gohttp/extconf.rb
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - LICENSE
94
+ - README.md
95
+ - Rakefile
96
+ - ext/gohttp/extconf.rb
97
+ - ext/gohttp/gohttp.go
98
+ - ext/gohttp/wrapper.go
99
+ - gohttp.gemspec
100
+ - lib/gohttp.rb
101
+ - lib/gohttp/version.rb
102
+ - test.rb
103
+ homepage: https://github.com/nurse/gohttp
104
+ licenses:
105
+ - BSD-2-Clause
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '2.0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.4.5
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: an http library with go.
127
+ test_files: []
128
+ has_rdoc: