Skip to content

Commit

Permalink
fix: everything else
Browse files Browse the repository at this point in the history
  • Loading branch information
Fluf22 committed Sep 4, 2024
1 parent e69ab88 commit 0519875
Show file tree
Hide file tree
Showing 32 changed files with 151 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,30 @@
import java.io.Closeable;

/**
* Represents a mechanism for executing HTTP requests and deserializing
* responses. It provides
* methods for making requests and returning the desired object representation.
* Implementations of
* Represents a mechanism for executing HTTP requests and deserializing responses. It provides
* methods for making requests and returning the desired object representation. Implementations of
* this interface should ensure proper resource management.
*/
public interface Requester extends Closeable {
/**
* Executes an HTTP request and deserializes the response into a specified Java
* type.
* Executes an HTTP request and deserializes the response into a specified Java type.
*
* @param <T> The type of the returned object.
* @param httpRequest The HTTP request to be executed.
* @param <T> The type of the returned object.
* @param httpRequest The HTTP request to be executed.
* @param requestOptions Optional request options.
* @param returnType The class of the response.
* @param innerType The inner class type if the response is a container
* type.
* @param returnType The class of the response.
* @param innerType The inner class type if the response is a container type.
* @return The deserialized response.
*/
<T> T execute(HttpRequest httpRequest, RequestOptions requestOptions, Class<?> returnType, Class<?> innerType);

/**
* Executes an HTTP request and deserializes the response into a specified type
* reference.
* Executes an HTTP request and deserializes the response into a specified type reference.
*
* @param <T> The type of the returned object.
* @param httpRequest The HTTP request to be executed.
* @param <T> The type of the returned object.
* @param httpRequest The HTTP request to be executed.
* @param requestOptions Optional request options.
* @param returnType The type reference of the response.
* @param returnType The type reference of the response.
* @return The deserialized response.
*/
<T> T execute(HttpRequest httpRequest, RequestOptions requestOptions, TypeReference<?> returnType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@
import okio.BufferedSink;

/**
* HttpRequester is responsible for making HTTP requests using the OkHttp
* client. It provides a
* mechanism for request serialization and deserialization using a given
* {@link JsonSerializer}.
* HttpRequester is responsible for making HTTP requests using the OkHttp client. It provides a
* mechanism for request serialization and deserialization using a given {@link JsonSerializer}.
*/
public final class HttpRequester implements Requester {

Expand All @@ -35,11 +33,11 @@ public final class HttpRequester implements Requester {
/** Private constructor initialized using the builder pattern. */
private HttpRequester(Builder builder, ClientConfig config) {
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.connectTimeout(config.getConnectTimeout())
.readTimeout(config.getReadTimeout())
.writeTimeout(config.getWriteTimeout())
.addInterceptor(new HeaderInterceptor(config.getDefaultHeaders()))
.addNetworkInterceptor(new LogInterceptor(config.getLogger(), config.getLogLevel()));
.connectTimeout(config.getConnectTimeout())
.readTimeout(config.getReadTimeout())
.writeTimeout(config.getWriteTimeout())
.addInterceptor(new HeaderInterceptor(config.getDefaultHeaders()))
.addNetworkInterceptor(new LogInterceptor(config.getLogger(), config.getLogLevel()));
builder.interceptors.forEach(clientBuilder::addInterceptor);
builder.networkInterceptors.forEach(clientBuilder::addNetworkInterceptor);
if (config.getCompressionType() == CompressionType.GZIP) {
Expand All @@ -53,8 +51,7 @@ private HttpRequester(Builder builder, ClientConfig config) {
}

@Override
public <T> T execute(HttpRequest httpRequest, RequestOptions requestOptions, Class<?> returnType,
Class<?> innerType) {
public <T> T execute(HttpRequest httpRequest, RequestOptions requestOptions, Class<?> returnType, Class<?> innerType) {
return execute(httpRequest, requestOptions, serializer.getJavaType(returnType, innerType));
}

Expand All @@ -80,8 +77,7 @@ private <T> T execute(@Nonnull HttpRequest httpRequest, RequestOptions requestOp
RequestBody requestBody = createRequestBody(httpRequest);

// Build the HTTP request.
Request request = new Request.Builder().url(url).headers(headers).method(httpRequest.getMethod(), requestBody)
.build();
Request request = new Request.Builder().url(url).headers(headers).method(httpRequest.getMethod(), requestBody).build();

// Get or adjust the HTTP client according to request options.
OkHttpClient client = getOkHttpClient(requestOptions);
Expand Down Expand Up @@ -110,9 +106,9 @@ private <T> T execute(@Nonnull HttpRequest httpRequest, RequestOptions requestOp
@Nonnull
private static HttpUrl createHttpUrl(@Nonnull HttpRequest request, RequestOptions requestOptions) {
HttpUrl.Builder urlBuilder = new HttpUrl.Builder()
.scheme("https")
.host("algolia.com") // will be overridden by the retry strategy
.encodedPath(request.getPath());
.scheme("https")
.host("algolia.com") // will be overridden by the retry strategy
.encodedPath(request.getPath());
request.getQueryParameters().forEach(urlBuilder::addEncodedQueryParameter);
if (requestOptions != null) {
requestOptions.getQueryParameters().forEach(urlBuilder::addEncodedQueryParameter);
Expand Down Expand Up @@ -160,15 +156,11 @@ private Headers createHeaders(@Nonnull HttpRequest request, RequestOptions reque
return builder.build();
}

/**
* Returns a suitable OkHttpClient instance based on the provided request
* options.
*/
/** Returns a suitable OkHttpClient instance based on the provided request options. */
@Nonnull
private OkHttpClient getOkHttpClient(RequestOptions requestOptions) {
// Return the default client if no request options are provided.
if (requestOptions == null)
return httpClient;
if (requestOptions == null) return httpClient;

// Create a new client builder from the default client and adjust timeouts if
// provided.
Expand All @@ -184,8 +176,7 @@ private OkHttpClient getOkHttpClient(RequestOptions requestOptions) {

@Override
public void close() throws IOException {
if (isClosed.get())
return;
if (isClosed.get()) return;
httpClient.dispatcher().executorService().shutdown();
httpClient.connectionPool().evictAll();
if (httpClient.cache() != null) {
Expand All @@ -195,8 +186,7 @@ public void close() throws IOException {
}

/**
* The Builder class for HttpRequester. It provides a mechanism for constructing
* an instance of
* The Builder class for HttpRequester. It provides a mechanism for constructing an instance of
* HttpRequester with customized configurations.
*/
public static class Builder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ private[algoliasearch] class HttpRequester private (
}

override def setAlgoliaApiKey(apiKey: String): Unit = {
httpClient.newBuilder().addInterceptor(new Interceptor {
override def intercept(chain: Interceptor.Chain): Response = {
val request = chain.request().newBuilder().addHeader("X-Algolia-API-Key", apiKey).build()
chain.proceed(request)
}
})
httpClient
.newBuilder()
.addInterceptor(new Interceptor {
override def intercept(chain: Interceptor.Chain): Response = {
val request = chain.request().newBuilder().addHeader("X-Algolia-API-Key", apiKey).build()
chain.proceed(request)
}
})
}

private val jsonSerializer = JsonSerializer()(builder.formats)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ open class Transporter {

self.requestBuilder = requestBuilder
}

public func setAlgoliaApiKey(apiKey: String) {
self.configuration.defaultHeaders?.updateValue(apiKey, forKey: "X-Algolia-API-Key")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.Map;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenResponse;
import org.openapitools.codegen.SupportingFile;

public class TestsClient extends TestsGenerator {
Expand Down Expand Up @@ -114,9 +115,25 @@ public void run(Map<String, CodegenModel> models, Map<String, CodegenOperation>
stepOut.put("returnType", Helpers.toPascalCase(ope.returnType));
}

stepOut.put("isHelper", (boolean) ope.vendorExtensions.getOrDefault("x-helper", false));

// default to true because most api calls are asynchronous
stepOut.put("isAsync", (boolean) ope.vendorExtensions.getOrDefault("x-asynchronous-helper", true));
// Determines whether the endpoint is expected to return a response payload
// deserialized and therefore a variable to store it into.
stepOut.put("hasResponsePayload", true);

for (CodegenResponse response : ope.responses) {
if (response.code.equals("204")) {
stepOut.put("hasResponsePayload", false);
}
}

// set on testOut because we need to wrap everything for java.
testOut.put("isHelper", (boolean) ope.vendorExtensions.getOrDefault("x-helper", false));
testOut.put("isAsync", (boolean) ope.vendorExtensions.getOrDefault("x-asynchronous-helper", true)); // default to true because most api calls are asynchronous

// default to true because most api calls are asynchronous
testOut.put("isAsync", (boolean) ope.vendorExtensions.getOrDefault("x-asynchronous-helper", true));
}

stepOut.put("method", step.method);
Expand Down
35 changes: 35 additions & 0 deletions scripts/cts/testServer/apiKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Server } from 'http';

import { expect } from 'chai';
import type { Express, Request, Response } from 'express';

import { setupServer } from '.';

function addRoutes(app: Express): void {
app.get('/check-api-key/1', (req: Request, res: Response) => {
const headerName = 'x-algolia-api-key';

// eslint-disable-next-line no-unused-expressions
expect(headerName in req.headers).to.be.true;

const headerAPIKeyValue = req.headers[headerName];
expect(headerAPIKeyValue).to.equal('test-api-key');

res.status(200).json({ headerAPIKeyValue });
});
app.get('/check-api-key/2', (req: Request, res: Response) => {
const headerName = 'x-algolia-api-key';

// eslint-disable-next-line no-unused-expressions
expect(headerName in req.headers).to.be.true;

const headerAPIKeyValue = req.headers[headerName];
expect(headerAPIKeyValue).to.equal('updated-api-key');

res.status(200).json({ headerAPIKeyValue });
});
}

export function apiKeyServer(): Promise<Server> {
return setupServer('apiKey', 6683, addRoutes);
}
4 changes: 3 additions & 1 deletion scripts/cts/testServer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { Express } from 'express';
import { createSpinner } from '../../spinners';
import type { CTSType } from '../runCts';

import { apiKeyServer } from './apiKey';
import { benchmarkServer } from './benchmark';
import { chunkWrapperServer } from './chunkWrapper';
import { gzipServer } from './gzip';
Expand All @@ -24,6 +25,7 @@ export async function startTestServer(suites: Record<CTSType, boolean>): Promise
replaceAllObjectsServer(),
chunkWrapperServer(),
waitForApiKeyServer(),
apiKeyServer(),
);
}
if (suites.benchmark) {
Expand Down Expand Up @@ -61,7 +63,7 @@ export async function setupServer(name: string, port: number, addRoutes: (app: E
});

// catch all error handler
app.use((err, req, res, _) => {
app.use((err, _req, res, _) => {
// eslint-disable-next-line no-console
console.error(err.message);
res.status(500).send({ message: err.message });
Expand Down
4 changes: 2 additions & 2 deletions scripts/cts/testServer/waitFor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,13 @@ function addRoutes(app: Express): void {
}
});

app.get('/1/indexes/:indexName/task/:taskID', (req, res) => {
app.get('/1/indexes/:indexName/task/:taskID', (_req, res) => {
res.status(200).json({
status: 'published',
});
});

app.get('/1/task/:taskID', (req, res) => {
app.get('/1/task/:taskID', (_req, res) => {
res.status(200).json({
status: 'published',
});
Expand Down
8 changes: 2 additions & 6 deletions specs/common/helpers/setAlgoliaApiKey.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ method:
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: string
'204':
description: No content.
'400':
$ref: '../../common/responses/IndexNotFound.yml'
2 changes: 1 addition & 1 deletion templates/csharp/tests/client/method.mustache
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{{^useEchoRequester}}var res = {{/useEchoRequester}}{{> tests/method}};
{{^useEchoRequester}}{{#hasResponsePayload}}var res = {{/hasResponsePayload}}{{/useEchoRequester}}{{> tests/method}};
{{#useEchoRequester}}EchoResponse result = _echo.LastResponse;{{/useEchoRequester}}
2 changes: 2 additions & 0 deletions templates/csharp/tests/client/tests.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
var client = new {{client}}(new {{clientPrefix}}Config("appId", "apiKey"{{#hasRegionalHost}},"{{defaultRegion}}"{{/hasRegionalHost}}), _echo);
{{/autoCreateClient}}
{{#steps}}
{
{{#times}}
for (int i = 0; i < {{.}}; i++) {
{{/times}}
Expand Down Expand Up @@ -46,6 +47,7 @@
{{#times}}
}
{{/times}}
}
{{/steps}}
}
{{/tests}}
4 changes: 3 additions & 1 deletion templates/dart/tests/client/client.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ void main() {
options: ClientOptions(requester: requester),
);
{{/autoCreateClient}}
{{#steps}}
{{#steps}}
{
{{#isError}}
await expectError(
'{{{expectedError}}}',
Expand All @@ -45,6 +46,7 @@ void main() {
{{/match}}
{{#dynamicTemplate}}{{/dynamicTemplate}}
{{/isError}}
}
{{/steps}}
}
);
Expand Down
2 changes: 1 addition & 1 deletion templates/dart/tests/client/method.mustache
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
try {
final res = await client.{{method}}(
{{#hasResponsePayload}}final res = {{/hasResponsePayload}}await client.{{method}}(
{{#parametersWithDataType}}
{{> tests/request_param}}
{{/parametersWithDataType}}
Expand Down
2 changes: 1 addition & 1 deletion templates/go/client.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (c *APIClient) GetConfiguration() *{{#lambda.titlecase}}{{#lambda.camelcase
}

// Allow update of stored API key used to authenticate requests.
func (c *APIClient) SetApiKey(apiKey string) {
func (c *APIClient) SetAlgoliaApiKey(apiKey string) {
c.cfg.ApiKey = apiKey
}

Expand Down
2 changes: 1 addition & 1 deletion templates/go/tests/client/method.mustache
Original file line number Diff line number Diff line change
@@ -1 +1 @@
res, err = {{> tests/method}}
{{#hasResponsePayload}}res, err = {{/hasResponsePayload}}{{> tests/method}}
2 changes: 2 additions & 0 deletions templates/go/tests/client/tests.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func Test{{#lambda.titlecase}}{{clientPrefix}}{{testType}}{{/lambda.titlecase}}{
{{/autoCreateClient}}
_ = echo
{{#steps}}
{
{{#times}}
for i := 0; i < {{.}}; i++ {
{{/times}}
Expand Down Expand Up @@ -56,6 +57,7 @@ func Test{{#lambda.titlecase}}{{clientPrefix}}{{testType}}{{/lambda.titlecase}}{
{{#times}}
}
{{/times}}
}
{{/steps}}
}

Expand Down
2 changes: 1 addition & 1 deletion templates/java/tests/client/method.mustache
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{{^useEchoRequester}}var res = {{/useEchoRequester}}{{> tests/method}};
{{^useEchoRequester}}{{#hasResponsePayload}}var res = {{/hasResponsePayload}}{{/useEchoRequester}}{{> tests/method}};
{{#useEchoRequester}}EchoResponse result = echo.getLastResponse();{{/useEchoRequester}}
Loading

0 comments on commit 0519875

Please sign in to comment.