postrank-labs / goliath

Goliath is a non-blocking Ruby web server framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

response different type for json type

sforce100 opened this issue · comments

I also use Grape gem,and set ' content_type :json, "application/json;charset=UTF-8"'

In my action, i had format my result to_json

the same code run in different matchine,I get different response body.see below of the code with 'parsed_response'.

1.9.3-p429 :024 > HTTParty.send('get',"http://192.168.1.1:3001/locate/province/25")
 => #<HTTParty::Response:0x4e5bb50 parsed_response="{\"id\":25,\"province_name\":\"\\u5e7f\\u4e1c\"}", @response=#<Net::HTTPOK 200 OK readbody=true>, @headers={"access-control-allow-origin"=>["*"], "access-control-request-method"=>["*"], "content-type"=>["application/json;charset=UTF-8"], "content-length"=>["50"], "server"=>["Goliath"], "date"=>["Fri, 28 Jun 2013 03:18:53 GMT"]}> 
1.9.3-p429 :025 > HTTParty.send('get',"http://192.168.1.2:3001/locate/province/25")
 => #<HTTParty::Response:0x4e78548 parsed_response={"id"=>25, "province_name"=>"广东"}, @response=#<Net::HTTPOK 200 OK readbody=true>, @headers={"access-control-allow-origin"=>["*"], "access-control-request-method"=>["*"], "content-type"=>["application/json;charset=UTF-8"], "content-length"=>["40"], "server"=>["Goliath"], "date"=>["Fri, 28 Jun 2013 03:19:05 GMT"]}> 

Can you share an example of your server code? You're double encoding your JSON in the first example.

@igrigorik

" You're double encoding your JSON in the first example." I note this, but my hesitation is that it response different content.

here is my code example, thanks:

module SwaggerDemo

  class API < Grape::API
    # version 'v1', :using => :path
    content_type :json, "application/json;charset=UTF-8"
    format :json

    before do
      header['Access-Control-Allow-Origin'] = '*'
      header['Access-Control-Request-Method'] = '*'
    end

   resource 'locate' do
    get "/province/:province_id" do
        province = Province.where(:id => params[:province_id]).first
        {:id => province.id, :province_name => province.province_name}.to_json
     end
    end
 end

I don't think that's all of it, is it? There needs to be a wrapper for Goliath as well... Which versino of Goliath? This likely has been addressed in latest release already.

@igrigorik

my goliath config nothing special, all by default.
Goliath version:1.0.1

class Application < Goliath::API

  Goliath::Server::DEFAULT_PORT = 3721
  # use Goliath::Rack::Heartbeat
  # use Goliath::Rack::Formatters::JSON

  ENV['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.AL32UTF8'
  ENV['NLS_NCHAR'] = 'SIMPLIFIED CHINESE_CHINA.ZHS16GBK'

  def response(env)
    ::SwaggerDemo::Root.call(env)
  end

end

Appears to work here, I'm not sure what the issue is...

require 'goliath'
require 'grape'

module SwaggerDemo
  class API < Grape::API
    content_type :json, "application/json;charset=UTF-8"
    format :json

    before do
      header['Access-Control-Allow-Origin'] = '*'
      header['Access-Control-Request-Method'] = '*'
    end

    resource 'locate' do
      get "/province/:province_id" do
        {:id => 'a', :province_name => 'b'}
      end
    end
 end
end

class Application < Goliath::API
  def response(env)
    SwaggerDemo::API.call(env)
  end
end

Above forces json output on all requests.

@igrigorik

The issue is that as you say " forces json output on all requests.".
I deploy this code on two matchines 192.168.1.1 and 192.168.1.2.
I send the same resquest to thoes matchines.
192.168.1.1 return a hash.

{"id"=>25, "province_name"=>"广东"}

192.168.1.2 return a json string.

"{\"id\":25,\"province_name\":\"\\u5e7f\\u4e1c\"}

Is the matchine env params case this?

Can you show me the full request headers from both machines? Try it with curl.

@igrigorik

here is request header

curl result is the same as above

192.168.1.1

Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Cache-Control   max-age=0
Connection  keep-alive
Host    192.168.1.1:3721
User-Agent  Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20100101 Firefox/21.0

192.168.1.2

Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Cache-Control   max-age=0
Connection  keep-alive
Cookie  remember_user_token=.......................
Host    192.168.1.2:3721
User-Agent  Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20100101 Firefox/21.0

And is the response different in these cases?

$> curl -vv http://server/resource

@igrigorik

curl result is the same as above.

$ curl-w/ http://192.168.1.1:3721/locate/province/25.json
{"id":25, "province_name":"广东"}

$ curl-w/ http://192.168.1.1:3721/locate/province/25.json
"{\"id\":25,\"province_name\":\"\\u5e7f\\u4e1c\"}

response header :

Access-Control-Allow-Orig...    *
Access-Control-Request-Me...    *
Content-Length  40
Content-Type    application/json;charset=UTF-8
Date    Sat, 29 Jun 2013 19:03:33 GMT
Server  Goliath

Can you please paste the full request-response cycle? I can't help otherwise... i.e. curl -vv resource

@igrigorik

the cycle almost the same.

curl -vv 192.168.1.1

* About to connect() to 192.168.1.1 port 3721 (#0)
*   Trying 192.168.9.158... connected
* Connected to 192.168.1.1(192.168.9.158) port 3721 (#0)
> GET /locate/province/25.json HTTP/1.1
> User-Agent: curl/7.21.6 (x86_64-pc-linux-gnu) libcurl/7.21.6 OpenSSL/1.0.0e zlib/1.2.3.4 libidn/1.22 librtmp/2.3
> Host: 192.168.9.158:3721
> Accept: */*
> 
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Access-Control-Request-Method: *
< Content-Type: application/json;charset=UTF-8
< Content-Length: 40
< Server: Goliath
< Date: Sat, 29 Jun 2013 20:36:43 GMT
< 
* Connection #0 to host 192.168.1.1 left intact
* Closing connection #0
{"id":25,"province_name":"\u5e7f\u4e1c"}

curl -vv 192.168.1.2

* About to connect() to 192.168.1.2 port 3721 (#0)
*   Trying 192.168.1.2... connected
* Connected to 192.168.9.16 (192.168.9.16) port 3721 (#0)
> GET /locate/province/25.json HTTP/1.1
> User-Agent: curl/7.21.6 (x86_64-pc-linux-gnu) libcurl/7.21.6 OpenSSL/1.0.0e zlib/1.2.3.4 libidn/1.22 librtmp/2.3
> Host: 192.168.1.1:3721
> Accept: */*
> 
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Access-Control-Request-Method: *
< Content-Type: application/json;charset=UTF-8
< Content-Length: 50
< Server: Goliath
< Date: Sat, 29 Jun 2013 20:33:35 GMT
< 
* Connection #0 to host 192.168.1.2 left intact
* Closing connection #0
"{\"id\":25,\"province_name\":\"\\u5e7f\\u4e1c\"}"

There is a big difference here.. You're connecting to two different hosts. Are you sure they're running the same code, ruby version, versino of libraries? For sake of sanity, copy the code from .1. to .2.

@igrigorik
I am sure there use the same code.I use cap to deploy and deploy many times. And i had make a .rmvrc file, so the they use the same ruby version.Otherwise, i have add my gemfile.lock to my project, so the libraries version same too. Everything is the same. So, i doubt that is the matchine environment case this.

Well... then it doesn't make sense, does it? The same code should produce the same results given the same input. :)

I'm not ruling out that it could be something in Goliath, but given the setup here, I can't see what / why would be broken in core. My guess is that this is a deployment or application code issue.

@igrigorik
I am very sorry about this issue.It can be my deployment problem. Two matchine Grape gem in different version.

cool, glad you got it working!