Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for overriding various fields of outgoing requests #224

Merged
merged 8 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Nylas Java SDK Changelog

## Unreleased

### Added
* Added support for overriding various fields of outgoing requests

## [2.2.1] - Released 2024-03-05

### Added
Expand Down
80 changes: 62 additions & 18 deletions src/main/kotlin/com/nylas/NylasClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -188,16 +188,18 @@ class NylasClient(
* @param path The path to request.
* @param resultType The type of the response body.
* @param queryParams The query parameters.
* @param overrides The request overrides.
* @suppress Not for public use.
*/
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
fun <T> executeGet(
path: String,
resultType: Type,
queryParams: IQueryParams? = null,
overrides: RequestOverrides? = null,
): T {
val url = buildUrl(path, queryParams)
return executeRequest(url, HttpMethod.GET, null, resultType)
val url = buildUrl(path, queryParams, overrides)
return executeRequest(url, HttpMethod.GET, null, resultType, overrides)
}

/**
Expand All @@ -206,6 +208,7 @@ class NylasClient(
* @param resultType The type of the response body.
* @param requestBody The request body.
* @param queryParams The query parameters.
* @param overrides The request overrides.
* @suppress Not for public use.
*/
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
Expand All @@ -214,10 +217,11 @@ class NylasClient(
resultType: Type,
requestBody: String? = null,
queryParams: IQueryParams? = null,
overrides: RequestOverrides? = null,
): T {
val url = buildUrl(path, queryParams)
val url = buildUrl(path, queryParams, overrides)
val jsonBody = if (requestBody != null) JsonHelper.jsonRequestBody(requestBody) else null
return executeRequest(url, HttpMethod.PUT, jsonBody, resultType)
return executeRequest(url, HttpMethod.PUT, jsonBody, resultType, overrides)
}

/**
Expand All @@ -226,6 +230,7 @@ class NylasClient(
* @param resultType The type of the response body.
* @param requestBody The request body.
* @param queryParams The query parameters.
* @param overrides The request overrides.
* @suppress Not for public use.
*/
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
Expand All @@ -234,10 +239,11 @@ class NylasClient(
resultType: Type,
requestBody: String? = null,
queryParams: IQueryParams? = null,
overrides: RequestOverrides? = null,
): T {
val url = buildUrl(path, queryParams)
val url = buildUrl(path, queryParams, overrides)
val jsonBody = if (requestBody != null) JsonHelper.jsonRequestBody(requestBody) else null
return executeRequest(url, HttpMethod.PATCH, jsonBody, resultType)
return executeRequest(url, HttpMethod.PATCH, jsonBody, resultType, overrides)
}

/**
Expand All @@ -246,6 +252,7 @@ class NylasClient(
* @param resultType The type of the response body.
* @param requestBody The request body.
* @param queryParams The query parameters.
* @param overrides The request overrides.
* @suppress Not for public use.
*/
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
Expand All @@ -254,30 +261,33 @@ class NylasClient(
resultType: Type,
requestBody: String? = null,
queryParams: IQueryParams? = null,
overrides: RequestOverrides? = null,
): T {
val url = buildUrl(path, queryParams)
val url = buildUrl(path, queryParams, overrides)
var jsonBody = RequestBody.create(null, ByteArray(0))
if (requestBody != null) {
jsonBody = JsonHelper.jsonRequestBody(requestBody)
}
return executeRequest(url, HttpMethod.POST, jsonBody, resultType)
return executeRequest(url, HttpMethod.POST, jsonBody, resultType, overrides)
}

/**
* Execute a DELETE request to the Nylas API.
* @param path The path to request.
* @param resultType The type of the response body.
* @param queryParams The query parameters.
* @param overrides The request overrides.
* @suppress Not for public use.
*/
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
fun <T> executeDelete(
path: String,
resultType: Type,
queryParams: IQueryParams? = null,
overrides: RequestOverrides? = null,
): T {
val url = buildUrl(path, queryParams)
return executeRequest(url, HttpMethod.DELETE, null, resultType)
val url = buildUrl(path, queryParams, overrides)
return executeRequest(url, HttpMethod.DELETE, null, resultType, overrides)
}

/**
Expand All @@ -287,6 +297,7 @@ class NylasClient(
* @param requestBody The form-data request body.
* @param resultType The type of the response body.
* @param queryParams The query parameters.
* @param overrides The request overrides.
* @suppress Not for public use.
*/
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
Expand All @@ -296,18 +307,31 @@ class NylasClient(
requestBody: RequestBody,
resultType: Type,
queryParams: IQueryParams? = null,
overrides: RequestOverrides? = null,
): T {
val url = buildUrl(path, queryParams)
return executeRequest(url, method, requestBody, resultType)
val url = buildUrl(path, queryParams, overrides)
return executeRequest(url, method, requestBody, resultType, overrides)
}

private fun buildRequest(
url: HttpUrl.Builder,
method: HttpMethod,
body: RequestBody?,
overrides: RequestOverrides?,
): Request {
val builder = Request.Builder().url(url.build())

// Override the API key if it is provided in the override
val apiKey = overrides?.apiKey ?: this.apiKey
builder.addHeader(HttpHeaders.AUTHORIZATION.headerName, "Bearer $apiKey")

// Add additional headers
if (overrides?.headers != null) {
for ((key, value) in overrides.headers) {
builder.addHeader(key, value)
}
}

return builder.method(method.toString(), body).build()
}

Expand All @@ -317,6 +341,7 @@ class NylasClient(
* @param method The HTTP method to use.
* @param body The request body.
* @param resultType The type of the response body.
* @param overrides The request overrides.
* @suppress Not for public use.
*/
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
Expand All @@ -325,8 +350,9 @@ class NylasClient(
method: HttpMethod,
body: RequestBody?,
resultType: Type,
overrides: RequestOverrides? = null,
): T {
val responseBody = this.executeRequestRawResponse(url, method, body)
val responseBody = this.executeRequestRawResponse(url, method, body, overrides)
val adapter = JsonHelper.moshi().adapter<T>(resultType)
val serializedObject = adapter?.fromJson(responseBody.source()) ?: throw Exception("Failed to deserialize response body")
responseBody.close()
Expand All @@ -337,20 +363,31 @@ class NylasClient(
fun downloadResponse(
path: String,
queryParams: IQueryParams? = null,
overrides: RequestOverrides? = null,
): ResponseBody {
val url = buildUrl(path, queryParams)
return this.executeRequestRawResponse(url, HttpMethod.GET, null)
val url = buildUrl(path, queryParams, overrides)
return this.executeRequestRawResponse(url, HttpMethod.GET, null, overrides)
}

@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
private fun executeRequestRawResponse(
url: HttpUrl.Builder,
method: HttpMethod,
body: RequestBody?,
overrides: RequestOverrides?,
): ResponseBody {
val request = buildRequest(url, method, body)
val request = buildRequest(url, method, body, overrides)
val finalUrl = url.build()
try {
// Use the provided timeout if it is set in the overrides.
val httpClient = overrides?.timeout?.let { timeout ->
httpClient.newBuilder()
.callTimeout(timeout, TimeUnit.SECONDS)
.readTimeout(timeout, TimeUnit.SECONDS)
.writeTimeout(timeout, TimeUnit.SECONDS)
.build()
} ?: httpClient

val response = httpClient.newCall(request).execute()
throwAndCloseOnFailedRequest(finalUrl, response)
return response.body() ?: throw Exception("Unexpected null response body")
Expand Down Expand Up @@ -422,11 +459,18 @@ class NylasClient(
)
}

private fun buildUrl(path: String, queryParams: IQueryParams?): HttpUrl.Builder {
var url = newUrlBuilder().addPathSegments(path)
private fun buildUrl(path: String, queryParams: IQueryParams?, overrides: RequestOverrides?): HttpUrl.Builder {
// Sets the API URI if it is provided in the overrides.
var url = if (overrides?.apiUri != null) {
HttpUrl.get(overrides.apiUri).newBuilder().addPathSegments(path)
} else {
newUrlBuilder().addPathSegments(path)
}

if (queryParams != null) {
url = addQueryParams(url, queryParams.convertToMap())
}

return url
}

Expand Down
58 changes: 58 additions & 0 deletions src/main/kotlin/com/nylas/models/RequestOverrides.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.nylas.models

/**
* Overrides to use for an outgoing request to the Nylas API.
*/
data class RequestOverrides(
/**
* The API key to use for the request.
*/
val apiKey: String? = null,
/**
* The API URI to use for the request.
*/
val apiUri: String? = null,
/**
* The timeout to use for the request.
*/
val timeout: Long? = null,
/**
* Additional headers to include in the request.
*/
val headers: Map<String, String>? = emptyMap(),
) {
/**
* Builder for [RequestOverrides].
*/
class Builder {
private var apiKey: String? = null
private var apiUri: String? = null
private var timeout: Long? = null
private var headers: Map<String, String>? = null

/**
* Set the API key to use for the request.
*/
fun apiKey(apiKey: String) = apply { this.apiKey = apiKey }

/**
* Set the API URI to use for the request.
*/
fun apiUri(apiUri: String) = apply { this.apiUri = apiUri }

/**
* Set the timeout to use for the request.
*/
fun timeout(timeout: Long) = apply { this.timeout = timeout }

/**
* Add additional headers to include in the request.
*/
fun headers(headers: Map<String, String>) = apply { this.headers = headers }

/**
* Build the [RequestOverrides].
*/
fun build() = RequestOverrides(apiKey, apiUri, timeout, headers)
}
}
11 changes: 5 additions & 6 deletions src/main/kotlin/com/nylas/resources/Applications.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.nylas.resources

import com.nylas.NylasClient
import com.nylas.models.ApplicationDetails
import com.nylas.models.NylasApiError
import com.nylas.models.NylasSdkTimeoutError
import com.nylas.models.Response
import com.nylas.models.*
import com.squareup.moshi.Types

/**
Expand All @@ -23,12 +20,14 @@ class Applications(private val client: NylasClient) {

/**
* Get application details
* @param overrides Optional request overrides to apply
* @return The application details
*/
@Throws(NylasApiError::class, NylasSdkTimeoutError::class)
fun getDetails(): Response<ApplicationDetails> {
@JvmOverloads
fun getDetails(overrides: RequestOverrides? = null): Response<ApplicationDetails> {
val path = "v3/applications"
val responseType = Types.newParameterizedType(Response::class.java, ApplicationDetails::class.java)
return client.executeGet(path, responseType)
return client.executeGet(path, responseType, overrides = overrides)
}
}
18 changes: 12 additions & 6 deletions src/main/kotlin/com/nylas/resources/Attachments.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ class Attachments(client: NylasClient) : Resource<Attachment>(client, Attachment
* @param identifier Grant ID or email account to query
* @param attachmentId The id of the attachment to retrieve.
* @param queryParams The query parameters to include in the request
* @param overrides Optional request overrides to apply
* @return The attachment metadata
*/
@Throws(NylasOAuthError::class, NylasSdkTimeoutError::class)
fun find(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams): Response<Attachment> {
@JvmOverloads
fun find(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams, overrides: RequestOverrides? = null): Response<Attachment> {
val path = String.format("v3/grants/%s/attachments/%s", identifier, attachmentId)
return findResource(path, queryParams)
return findResource(path, queryParams, overrides = overrides)
}

/**
Expand All @@ -37,25 +39,29 @@ class Attachments(client: NylasClient) : Resource<Attachment>(client, Attachment
* @param identifier Grant ID or email account to query
* @param attachmentId The id of the attachment to download.
* @param queryParams The query parameters to include in the request
* @param overrides Optional request overrides to apply
* @return The [ResponseBody] containing the file data
*/
@Throws(NylasOAuthError::class, NylasSdkTimeoutError::class)
fun download(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams): ResponseBody {
@JvmOverloads
fun download(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams, overrides: RequestOverrides? = null): ResponseBody {
val path = String.format("v3/grants/%s/attachments/%s/download", identifier, attachmentId)

return client.downloadResponse(path, queryParams)
return client.downloadResponse(path, queryParams, overrides = overrides)
}

/**
* Download the attachment as a byte array
* @param identifier Grant ID or email account to query
* @param attachmentId The id of the attachment to download.
* @param queryParams The query parameters to include in the request
* @param overrides Optional request overrides to apply
* @return The raw file data
*/
@Throws(NylasOAuthError::class, NylasSdkTimeoutError::class)
fun downloadBytes(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams): ByteArray {
val download = download(identifier, attachmentId, queryParams)
@JvmOverloads
fun downloadBytes(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams, overrides: RequestOverrides? = null): ByteArray {
val download = download(identifier, attachmentId, queryParams, overrides)
val fileBytes = download.bytes()
download.close()
return fileBytes
Expand Down
Loading
Loading