Skip to content

Commit 624bcab

Browse files
authored
Merge 855b0dd into 14989b8
2 parents 14989b8 + 855b0dd commit 624bcab

File tree

14 files changed

+101
-13
lines changed

14 files changed

+101
-13
lines changed

clients/algoliasearch-client-java/algoliasearch/src/main/java/com/algolia/internal/interceptors/RetryStrategy.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ private Response handleResponse(StatefulHost host, @Nonnull Response response) t
8484

8585
try {
8686
String message = response.body() != null ? response.body().string() : response.message();
87+
if (response.header("Content-Type", "application/json").contains("text/html")) {
88+
message = response.message();
89+
}
8790
throw isRetryable(response)
8891
? new AlgoliaRequestException(message, response.code())
8992
: new AlgoliaApiException(message, response.code());

clients/algoliasearch-client-javascript/packages/client-common/src/transporter/helpers.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,29 @@ export function deserializeSuccess<TObject>(response: Response): TObject {
8282
}
8383
}
8484

85+
const httpMessages: Record<number, string> = {
86+
400: 'Bad Request',
87+
401: 'Unauthorized',
88+
402: 'Payment Required',
89+
403: 'Forbidden',
90+
404: 'Not Found',
91+
405: 'Method Not Allowed',
92+
406: 'Not Acceptable',
93+
407: 'Proxy Authentication Required',
94+
408: 'Request Timeout',
95+
409: 'Conflict',
96+
410: 'Gone',
97+
411: 'Length Required',
98+
412: 'Precondition Required',
99+
413: 'Request Entry Too Large',
100+
414: 'Request-URI Too Long',
101+
415: 'Unsupported Media Type',
102+
416: 'Requested Range Not Satisfiable',
103+
417: 'Expectation Failed',
104+
418: 'I\'m a teapot',
105+
429: 'Too Many Requests',
106+
}
107+
85108
export function deserializeFailure({ content, status }: Response, stackFrame: StackFrame[]): Error {
86109
try {
87110
const parsed = JSON.parse(content);
@@ -92,5 +115,5 @@ export function deserializeFailure({ content, status }: Response, stackFrame: St
92115
} catch {
93116
// ..
94117
}
95-
return new ApiError(content, status, stackFrame);
118+
return new ApiError(status in httpMessages ? httpMessages[status] : content, status, stackFrame);
96119
}

clients/algoliasearch-client-php/lib/Http/CurlHttpClient.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,12 @@ public function sendRequest(
116116
$statusCode = (int) curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);
117117
$responseBody = curl_multi_getcontent($curlHandle);
118118
$error = curl_error($curlHandle);
119+
$contentType = curl_getinfo($curlHandle, CURLINFO_CONTENT_TYPE);
119120

120121
$this->releaseMHandle($curlHandle);
121122
curl_close($curlHandle);
122123

123-
return new Response($statusCode, [], $responseBody, '1.1', $error);
124+
return new Response($statusCode, ['Content-Type' => $contentType], $responseBody, '1.1', $error);
124125
}
125126

126127
private function getMHandle($curlHandle)

clients/algoliasearch-client-php/lib/RetryStrategy/ApiWrapper.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,11 @@ private function handleResponse(
247247
throw new RetriableException('Retriable failure on '.$request->getUri()->getHost().': '.$reason, $statusCode);
248248
}
249249

250+
// handle HTML error responses
251+
if (false !== strpos($response->getHeaderLine('Content-Type'), 'text/html')) {
252+
throw new AlgoliaException($statusCode.': '.$response->getReasonPhrase(), $statusCode);
253+
}
254+
250255
$responseArray = Helpers::json_decode($body, true);
251256

252257
if (404 === $statusCode) {

clients/algoliasearch-client-ruby/lib/algolia/error.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ def initialize(message, errors = [])
2727
# which is also included in the response attribute.
2828
#
2929
class AlgoliaHttpError < AlgoliaError
30-
attr_accessor :code, :message
30+
attr_accessor :code, :http_message
3131

3232
def initialize(code, message)
3333
self.code = code
34-
self.message = message
35-
super("#{self.code()}: #{self.message()}")
34+
self.http_message = message
35+
super("#{code}: #{message}")
3636
end
3737
end
3838
end

clients/algoliasearch-client-ruby/lib/algolia/transport/http/http_requester.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ def send_request(host, method, path, body, query_params, headers, timeout, conne
3939
@logger.info("Request succeeded. Response status: #{response.status}, body: #{response.body}")
4040
end
4141

42-
return Http::Response.new(status: response.status, body: response.body, headers: response.headers)
42+
return Http::Response.new(status: response.status, reason_phrase: response.reason_phrase, body: response.body, headers: response.headers)
4343
end
4444

4545
if ENV["ALGOLIA_DEBUG"]
4646
@logger.info("Request failed. Response status: #{response.status}, error: #{response.body}")
4747
end
4848

49-
Http::Response.new(status: response.status, error: response.body, headers: response.headers)
49+
Http::Response.new(status: response.status, reason_phrase: response.reason_phrase, error: response.body, headers: response.headers)
5050
rescue Faraday::TimeoutError => e
5151
@logger.info("Request timed out. Error: #{e.message}") if ENV["ALGOLIA_DEBUG"]
5252
Http::Response.new(error: e.message, has_timed_out: true)

clients/algoliasearch-client-ruby/lib/algolia/transport/http/response.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
module Algolia
22
module Http
33
class Response
4-
attr_reader :status, :body, :error, :headers, :has_timed_out, :network_failure
4+
attr_reader :status, :reason_phrase, :body, :error, :headers, :has_timed_out, :network_failure
55

66
# used for the echo requester
77
attr_reader :method, :path, :query_params, :host, :timeout, :connect_timeout
88

99
#
1010
# @option status [String] Response status
11+
# @option reason_phrase [String] Response reason phrase
1112
# @option body [String] Response body
1213
# @option error [String] Response error or caught error
1314
# @option headers [String] Response headers
1415
# @option has_timed_out [String] If the request has timed out
1516
#
1617
def initialize(opts = {})
1718
@status = opts[:status]
19+
@reason_phrase = opts[:reason_phrase]
1820
@body = opts[:body]
1921
@error = opts[:error] || ""
2022
@headers = opts[:headers] || ""

clients/algoliasearch-client-ruby/lib/algolia/transport/transport.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ def request(call_type, method, path, body, opts = {})
6969
network_failure: response.network_failure
7070
)
7171
if outcome == FAILURE
72+
# handle HTML error
73+
if response.headers["content-type"]&.include?("text/html")
74+
raise Algolia::AlgoliaHttpError.new(response.status, response.reason_phrase)
75+
end
76+
7277
decoded_error = JSON.parse(response.error, :symbolize_names => true)
7378
raise Algolia::AlgoliaHttpError.new(response.status, decoded_error[:message])
7479
end

scripts/cts/testServer/timeout.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ function addRoutes(app: express.Express): void {
9797

9898
// no response, just hang
9999
});
100+
101+
app.get('/1/html-error', (req, res) => {
102+
res.setHeader('Content-Type', 'text/html');
103+
res.status(429).send('<html><body>429 Too Many Requests</body></html>');
104+
});
100105
}
101106

102107
export function timeoutServer(): Promise<Server> {

templates/ruby/tests/client/tests.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
{{#dynamicTemplate}}{{/dynamicTemplate}}
1919
assert(false, 'An error should have been raised')
2020
rescue => e
21-
assert_equal({{#lambda.codeSnakeCase}}'{{{expectedError}}}'{{/lambda.codeSnakeCase}}.sub('%localhost%', ENV.fetch('CI', nil) == 'true' ? 'localhost' : 'host.docker.internal'), e.message)
21+
assert_equal({{#lambda.codeSnakeCase}}%q({{{expectedError}}}){{/lambda.codeSnakeCase}}.sub('%localhost%', ENV.fetch('CI', nil) == 'true' ? 'localhost' : 'host.docker.internal'), e.message)
2222
end
2323
{{/isError}}
2424
{{^isError}}

0 commit comments

Comments
 (0)