#160 - Add option to set encoding of response body
This commit is contained in:
parent
91ae01aa83
commit
fda7288859
|
@ -31,6 +31,7 @@ require 'google/api_client/media'
|
|||
require 'google/api_client/service_account'
|
||||
require 'google/api_client/batch'
|
||||
require 'google/api_client/gzip'
|
||||
require 'google/api_client/charset'
|
||||
require 'google/api_client/client_secrets'
|
||||
require 'google/api_client/railtie' if defined?(Rails)
|
||||
|
||||
|
@ -75,6 +76,9 @@ module Google
|
|||
# @option options [String] :ca_file
|
||||
# Optional set of root certificates to use when validating SSL connections.
|
||||
# By default, a bundled set of trusted roots will be used.
|
||||
# @options options[Hash] :force_encoding
|
||||
# Experimental option. True if response body should be force encoded into the charset
|
||||
# specified in the Content-Type header. Mostly intended for compressed content.
|
||||
# @options options[Hash] :faraday_options
|
||||
# Pass through of options to set on the Faraday connection
|
||||
def initialize(options={})
|
||||
|
@ -119,6 +123,7 @@ module Google
|
|||
@discovered_apis = {}
|
||||
ca_file = options[:ca_file] || File.expand_path('../../cacerts.pem', __FILE__)
|
||||
self.connection = Faraday.new do |faraday|
|
||||
faraday.response :charset if options[:force_encoding]
|
||||
faraday.response :gzip
|
||||
faraday.options.params_encoder = Faraday::FlatParamsEncoder
|
||||
faraday.ssl.ca_file = ca_file
|
||||
|
@ -265,10 +270,12 @@ module Google
|
|||
# @param [String, Symbol] api The API name.
|
||||
# @param [String] version The desired version of the API.
|
||||
# @param [Addressable::URI] uri The URI of the discovery document.
|
||||
# @return [Google::APIClient::API] The service object.
|
||||
def register_discovery_uri(api, version, uri)
|
||||
api = api.to_s
|
||||
version = version || 'v1'
|
||||
@discovery_uris["#{api}:#{version}"] = uri
|
||||
discovered_api(api, version)
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -297,6 +304,7 @@ module Google
|
|||
# @param [String] version The desired version of the API.
|
||||
# @param [String, StringIO] discovery_document
|
||||
# The contents of the discovery document.
|
||||
# @return [Google::APIClient::API] The service object.
|
||||
def register_discovery_document(api, version, discovery_document)
|
||||
api = api.to_s
|
||||
version = version || 'v1'
|
||||
|
@ -311,6 +319,7 @@ module Google
|
|||
end
|
||||
@discovery_documents["#{api}:#{version}"] =
|
||||
MultiJson.load(discovery_document)
|
||||
discovered_api(api, version)
|
||||
end
|
||||
|
||||
##
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
require 'faraday'
|
||||
require 'zlib'
|
||||
|
||||
module Google
|
||||
class APIClient
|
||||
class Charset < Faraday::Response::Middleware
|
||||
include Google::APIClient::Logging
|
||||
|
||||
def charset_for_content_type(type)
|
||||
if type
|
||||
m = type.match(/(?:charset|encoding)="?([a-z0-9-]+)"?/i)
|
||||
if m
|
||||
return Encoding.find(m[1])
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def adjust_encoding(env)
|
||||
charset = charset_for_content_type(env[:response_headers]['content-type'])
|
||||
if charset && env[:body].encoding != charset
|
||||
env[:body].force_encoding(charset)
|
||||
end
|
||||
end
|
||||
|
||||
def on_complete(env)
|
||||
adjust_encoding(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Faraday::Response.register_middleware :charset => Google::APIClient::Charset
|
|
@ -0,0 +1,584 @@
|
|||
{
|
||||
"kind": "discovery#describeItem",
|
||||
"name": "zoo",
|
||||
"version": "v1",
|
||||
"description": "Zoo API used for testing",
|
||||
"basePath": "/zoo/",
|
||||
"rootUrl": "https://www.googleapis.com/",
|
||||
"servicePath": "zoo/v1/",
|
||||
"rpcPath": "/rpc",
|
||||
"parameters": {
|
||||
"alt": {
|
||||
"type": "string",
|
||||
"description": "Data format for the response.",
|
||||
"default": "json",
|
||||
"enum": [
|
||||
"json"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Responses with Content-Type of application/json"
|
||||
],
|
||||
"location": "query"
|
||||
},
|
||||
"fields": {
|
||||
"type": "string",
|
||||
"description": "Selector specifying which fields to include in a partial response.",
|
||||
"location": "query"
|
||||
},
|
||||
"key": {
|
||||
"type": "string",
|
||||
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
|
||||
"location": "query"
|
||||
},
|
||||
"oauth_token": {
|
||||
"type": "string",
|
||||
"description": "OAuth 2.0 token for the current user.",
|
||||
"location": "query"
|
||||
},
|
||||
"prettyPrint": {
|
||||
"type": "boolean",
|
||||
"description": "Returns response with indentations and line breaks.",
|
||||
"default": "true",
|
||||
"location": "query"
|
||||
},
|
||||
"quotaUser": {
|
||||
"type": "string",
|
||||
"description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.",
|
||||
"location": "query"
|
||||
},
|
||||
"userIp": {
|
||||
"type": "string",
|
||||
"description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.",
|
||||
"location": "query"
|
||||
}
|
||||
},
|
||||
"features": [
|
||||
"dataWrapper"
|
||||
],
|
||||
"schemas": {
|
||||
"Animal": {
|
||||
"id": "Animal",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"etag": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"default": "zoo#animal"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"photo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"filename": {
|
||||
"type": "string"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"hashAlgorithm": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "integer"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Animal2": {
|
||||
"id": "Animal2",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"default": "zoo#animal"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AnimalFeed": {
|
||||
"id": "AnimalFeed",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"etag": {
|
||||
"type": "string"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "Animal"
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"default": "zoo#animalFeed"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AnimalMap": {
|
||||
"id": "AnimalMap",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"etag": {
|
||||
"type": "string"
|
||||
},
|
||||
"animals": {
|
||||
"type": "object",
|
||||
"description": "Map of animal id to animal data",
|
||||
"additionalProperties": {
|
||||
"$ref": "Animal"
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"default": "zoo#animalMap"
|
||||
}
|
||||
}
|
||||
},
|
||||
"LoadFeed": {
|
||||
"id": "LoadFeed",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"doubleVal": {
|
||||
"type": "number"
|
||||
},
|
||||
"nullVal": {
|
||||
"type": "null"
|
||||
},
|
||||
"booleanVal": {
|
||||
"type": "boolean",
|
||||
"description": "True or False."
|
||||
},
|
||||
"anyVal": {
|
||||
"type": "any",
|
||||
"description": "Anything will do."
|
||||
},
|
||||
"enumVal": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"default": "zoo#loadValue"
|
||||
},
|
||||
"longVal": {
|
||||
"type": "integer"
|
||||
},
|
||||
"stringVal": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"default": "zoo#loadFeed"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"methods": {
|
||||
"query": {
|
||||
"path": "query",
|
||||
"id": "bigquery.query",
|
||||
"httpMethod": "GET",
|
||||
"parameters": {
|
||||
"q": {
|
||||
"type": "string",
|
||||
"location": "query",
|
||||
"required": false,
|
||||
"repeated": false
|
||||
},
|
||||
"i": {
|
||||
"type": "integer",
|
||||
"location": "query",
|
||||
"required": false,
|
||||
"repeated": false,
|
||||
"minimum": "0",
|
||||
"maximum": "4294967295",
|
||||
"default": "20"
|
||||
},
|
||||
"n": {
|
||||
"type": "number",
|
||||
"location": "query",
|
||||
"required": false,
|
||||
"repeated": false
|
||||
},
|
||||
"b": {
|
||||
"type": "boolean",
|
||||
"location": "query",
|
||||
"required": false,
|
||||
"repeated": false
|
||||
},
|
||||
"a": {
|
||||
"type": "any",
|
||||
"location": "query",
|
||||
"required": false,
|
||||
"repeated": false
|
||||
},
|
||||
"o": {
|
||||
"type": "object",
|
||||
"location": "query",
|
||||
"required": false,
|
||||
"repeated": false
|
||||
},
|
||||
"e": {
|
||||
"type": "string",
|
||||
"location": "query",
|
||||
"required": false,
|
||||
"repeated": false,
|
||||
"enum": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"er": {
|
||||
"type": "string",
|
||||
"location": "query",
|
||||
"required": false,
|
||||
"repeated": true,
|
||||
"enum": [
|
||||
"one",
|
||||
"two",
|
||||
"three"
|
||||
]
|
||||
},
|
||||
"rr": {
|
||||
"type": "string",
|
||||
"location": "query",
|
||||
"required": false,
|
||||
"repeated": true,
|
||||
"pattern": "[a-z]+"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"my": {
|
||||
"resources": {
|
||||
"favorites": {
|
||||
"methods": {
|
||||
"list": {
|
||||
"path": "favorites/@me/mine",
|
||||
"id": "zoo.animals.mine",
|
||||
"httpMethod": "GET",
|
||||
"parameters": {
|
||||
"max-results": {
|
||||
"location": "query",
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"resources": {
|
||||
"print": {
|
||||
"methods": {
|
||||
"assert": {
|
||||
"path": "global/print/assert",
|
||||
"id": "zoo.animals.mine",
|
||||
"httpMethod": "GET",
|
||||
"parameters": {
|
||||
"max-results": {
|
||||
"location": "query",
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animals": {
|
||||
"methods": {
|
||||
"crossbreed": {
|
||||
"path": "animals/crossbreed",
|
||||
"id": "zoo.animals.crossbreed",
|
||||
"httpMethod": "POST",
|
||||
"description": "Cross-breed animals",
|
||||
"response": {
|
||||
"$ref": "Animal2"
|
||||
},
|
||||
"mediaUpload": {
|
||||
"accept": [
|
||||
"image/png"
|
||||
],
|
||||
"protocols": {
|
||||
"simple": {
|
||||
"multipart": true,
|
||||
"path": "upload/activities/{userId}/@self"
|
||||
},
|
||||
"resumable": {
|
||||
"multipart": true,
|
||||
"path": "upload/activities/{userId}/@self"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"path": "animals/{name}",
|
||||
"id": "zoo.animals.delete",
|
||||
"httpMethod": "DELETE",
|
||||
"description": "Delete animals",
|
||||
"parameters": {
|
||||
"name": {
|
||||
"location": "path",
|
||||
"required": true,
|
||||
"description": "Name of the animal to delete",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"parameterOrder": [
|
||||
"name"
|
||||
]
|
||||
},
|
||||
"get": {
|
||||
"path": "animals/{name}",
|
||||
"id": "zoo.animals.get",
|
||||
"httpMethod": "GET",
|
||||
"description": "Get animals",
|
||||
"supportsMediaDownload": true,
|
||||
"parameters": {
|
||||
"name": {
|
||||
"location": "path",
|
||||
"required": true,
|
||||
"description": "Name of the animal to load",
|
||||
"type": "string"
|
||||
},
|
||||
"projection": {
|
||||
"location": "query",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"full"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Include everything"
|
||||
]
|
||||
}
|
||||
},
|
||||
"parameterOrder": [
|
||||
"name"
|
||||
],
|
||||
"response": {
|
||||
"$ref": "Animal"
|
||||
}
|
||||
},
|
||||
"getmedia": {
|
||||
"path": "animals/{name}",
|
||||
"id": "zoo.animals.get",
|
||||
"httpMethod": "GET",
|
||||
"description": "Get animals",
|
||||
"parameters": {
|
||||
"name": {
|
||||
"location": "path",
|
||||
"required": true,
|
||||
"description": "Name of the animal to load",
|
||||
"type": "string"
|
||||
},
|
||||
"projection": {
|
||||
"location": "query",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"full"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Include everything"
|
||||
]
|
||||
}
|
||||
},
|
||||
"parameterOrder": [
|
||||
"name"
|
||||
]
|
||||
},
|
||||
"insert": {
|
||||
"path": "animals",
|
||||
"id": "zoo.animals.insert",
|
||||
"httpMethod": "POST",
|
||||
"description": "Insert animals",
|
||||
"request": {
|
||||
"$ref": "Animal"
|
||||
},
|
||||
"response": {
|
||||
"$ref": "Animal"
|
||||
},
|
||||
"mediaUpload": {
|
||||
"accept": [
|
||||
"image/png"
|
||||
],
|
||||
"maxSize": "1KB",
|
||||
"protocols": {
|
||||
"simple": {
|
||||
"multipart": true,
|
||||
"path": "upload/activities/{userId}/@self"
|
||||
},
|
||||
"resumable": {
|
||||
"multipart": true,
|
||||
"path": "upload/activities/{userId}/@self"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"path": "animals",
|
||||
"id": "zoo.animals.list",
|
||||
"httpMethod": "GET",
|
||||
"description": "List animals",
|
||||
"parameters": {
|
||||
"max-results": {
|
||||
"location": "query",
|
||||
"description": "Maximum number of results to return",
|
||||
"type": "integer",
|
||||
"minimum": "0"
|
||||
},
|
||||
"name": {
|
||||
"location": "query",
|
||||
"description": "Restrict result to animals with this name",
|
||||
"type": "string"
|
||||
},
|
||||
"projection": {
|
||||
"location": "query",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"full"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Include absolutely everything"
|
||||
]
|
||||
},
|
||||
"start-token": {
|
||||
"location": "query",
|
||||
"description": "Pagination token",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"$ref": "AnimalFeed"
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"path": "animals/{name}",
|
||||
"id": "zoo.animals.patch",
|
||||
"httpMethod": "PATCH",
|
||||
"description": "Update animals",
|
||||
"parameters": {
|
||||
"name": {
|
||||
"location": "path",
|
||||
"required": true,
|
||||
"description": "Name of the animal to update",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"parameterOrder": [
|
||||
"name"
|
||||
],
|
||||
"request": {
|
||||
"$ref": "Animal"
|
||||
},
|
||||
"response": {
|
||||
"$ref": "Animal"
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"path": "animals/{name}",
|
||||
"id": "zoo.animals.update",
|
||||
"httpMethod": "PUT",
|
||||
"description": "Update animals",
|
||||
"parameters": {
|
||||
"name": {
|
||||
"location": "path",
|
||||
"description": "Name of the animal to update",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"parameterOrder": [
|
||||
"name"
|
||||
],
|
||||
"request": {
|
||||
"$ref": "Animal"
|
||||
},
|
||||
"response": {
|
||||
"$ref": "Animal"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"load": {
|
||||
"methods": {
|
||||
"list": {
|
||||
"path": "load",
|
||||
"id": "zoo.load.list",
|
||||
"httpMethod": "GET",
|
||||
"response": {
|
||||
"$ref": "LoadFeed"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"loadNoTemplate": {
|
||||
"methods": {
|
||||
"list": {
|
||||
"path": "loadNoTemplate",
|
||||
"id": "zoo.loadNoTemplate.list",
|
||||
"httpMethod": "GET"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scopedAnimals": {
|
||||
"methods": {
|
||||
"list": {
|
||||
"path": "scopedanimals",
|
||||
"id": "zoo.scopedAnimals.list",
|
||||
"httpMethod": "GET",
|
||||
"description": "List animals (scoped)",
|
||||
"parameters": {
|
||||
"max-results": {
|
||||
"location": "query",
|
||||
"description": "Maximum number of results to return",
|
||||
"type": "integer",
|
||||
"minimum": "0"
|
||||
},
|
||||
"name": {
|
||||
"location": "query",
|
||||
"description": "Restrict result to animals with this name",
|
||||
"type": "string"
|
||||
},
|
||||
"projection": {
|
||||
"location": "query",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"full"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Include absolutely everything"
|
||||
]
|
||||
},
|
||||
"start-token": {
|
||||
"location": "query",
|
||||
"description": "Pagination token",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"$ref": "AnimalFeed"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,8 @@ require 'compat/multi_json'
|
|||
require 'signet/oauth_1/client'
|
||||
require 'google/api_client'
|
||||
|
||||
fixtures_path = File.expand_path('../../../fixtures', __FILE__)
|
||||
|
||||
RSpec.describe Google::APIClient do
|
||||
include ConnectionHelpers
|
||||
CLIENT = Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
|
||||
|
@ -70,6 +72,15 @@ RSpec.describe Google::APIClient do
|
|||
expect(CLIENT.preferred_version('bogus')).to eq(nil)
|
||||
end
|
||||
|
||||
describe 'with zoo API' do
|
||||
it 'should return API instance registered from file' do
|
||||
zoo_json = File.join(fixtures_path, 'files', 'zoo.json')
|
||||
contents = File.open(zoo_json, 'rb') { |io| io.read }
|
||||
api = CLIENT.register_discovery_document('zoo', 'v1', contents)
|
||||
expect(api).to be_kind_of(Google::APIClient::API)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with the prediction API' do
|
||||
before do
|
||||
CLIENT.authorization = nil
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# Encoding: utf-8
|
||||
# Copyright 2012 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -20,6 +21,7 @@ RSpec.describe Google::APIClient::Gzip do
|
|||
|
||||
def create_connection(&block)
|
||||
Faraday.new do |b|
|
||||
b.response :charset
|
||||
b.response :gzip
|
||||
b.adapter :test do |stub|
|
||||
stub.get '/', &block
|
||||
|
@ -43,6 +45,17 @@ RSpec.describe Google::APIClient::Gzip do
|
|||
expect(result.body).to eq("Hello world\n")
|
||||
end
|
||||
|
||||
it 'should inflate with the correct charset encoding' do
|
||||
conn = create_connection do |env|
|
||||
[200,
|
||||
{ 'Content-Encoding' => 'deflate', 'Content-Type' => 'application/json;charset=BIG5'},
|
||||
Base64.decode64('eJxb8nLp7t2VAA8fBCI=')]
|
||||
end
|
||||
result = conn.get('/')
|
||||
expect(result.body.encoding).to eq(Encoding::BIG5)
|
||||
expect(result.body).to eq('日本語'.encode("BIG5"))
|
||||
end
|
||||
|
||||
describe 'with API Client' do
|
||||
|
||||
before do
|
||||
|
|
Loading…
Reference in New Issue