From 422eebf95afa9618fc46d3e188dc98eff096d635 Mon Sep 17 00:00:00 2001 From: verifalia Date: Sun, 28 Jun 2020 16:39:36 +0200 Subject: [PATCH] Aligned SDK to latest API version (v2.2) Added support for importing email addresses from a file / input stream / byte array Improved null values handling while serializing JSON data Fixed an issue with the charset used while serializing input data (https://github.com/verifalia/verifalia-java-sdk/issues/4) Refactored the way RestRequest builds Http requests --- README.md | 32 +- pom.xml | 8 +- .../verifalia/api/VerifaliaRestClient.java | 2 +- .../serialization/DurationSerializer.java | 4 +- .../EmailValidationsRestClient.java | 88 +++-- .../models/AbstractValidationRequest.java | 100 ++++++ .../models/FileValidationRequest.java | 334 ++++++++++++++++++ .../models/LineEndingMode.java | 26 ++ .../models/ValidationRequest.java | 46 +-- .../LineEndingModeSerializer.java | 53 +++ .../QualityLevelNameSerializer.java | 4 +- .../ValidationPrioritySerializer.java | 4 +- .../UnsupportedMediaTypeException.java | 47 +++ .../com/verifalia/api/rest/RestClient.java | 42 +-- .../com/verifalia/api/rest/RestRequest.java | 120 +++++-- .../api/rest/WellKnownMimeTypes.java | 31 ++ .../BearerAuthenticationProvider.java | 7 +- 17 files changed, 810 insertions(+), 138 deletions(-) create mode 100644 src/main/java/com/verifalia/api/emailvalidations/models/AbstractValidationRequest.java create mode 100644 src/main/java/com/verifalia/api/emailvalidations/models/FileValidationRequest.java create mode 100644 src/main/java/com/verifalia/api/emailvalidations/models/LineEndingMode.java create mode 100644 src/main/java/com/verifalia/api/emailvalidations/serialization/LineEndingModeSerializer.java create mode 100644 src/main/java/com/verifalia/api/exceptions/UnsupportedMediaTypeException.java create mode 100644 src/main/java/com/verifalia/api/rest/WellKnownMimeTypes.java diff --git a/README.md b/README.md index f0fadca..9a3e841 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Verifalia API](https://img.shields.io/badge/Verifalia%20API-v2.1-green) +![Verifalia API](https://img.shields.io/badge/Verifalia%20API-v2.2-green) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.verifalia/verifalia-java-sdk/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.verifalia/verifalia-java-sdk) Verifalia RESTful API - Java SDK and helper library @@ -214,6 +214,33 @@ verifalia Once deleted, a job is gone and there is no way to retrieve its email validation(s). +### How to import email addresses from a file ### + +In addition to submitting structured data (see the paragraphs above), it also possible to import the email addresses to +verify [from a file](https://verifalia.com/developers#email-validations-importing-file) provided by the user. Once submitted, +the email verification job follows the same flow as described above. + +Verifalia accepts the following file types: +- plain text files (.txt), with one email address per line +- comma-separated values (.csv), tab-separated values (.tsv) and other delimiter-separated values files +- Microsoft Excel spreadsheets (.xls and .xlsx) + +Here is how to extract and verify email addresses, for example, from the third column of the first sheet of an Excel workbook, +starting from the second row: + +```java +FileValidationRequest request = new FileValidationRequest("my-list.xlsx", + WellKnownMimeTypes.EXCEL_XLSX); + +// request.setSheet(0); // 0 is the default value +request.setColumn(2); // zero-based column number +request.setStartingRow(1); // zero-based starting row number + +Validation validation = verifalia + .getEmailValidations() + .submit(request); +``` + ### Iterating over your email validation jobs ### For management and reporting purposes, you may want to obtain a detailed list of your past email @@ -297,8 +324,7 @@ Iterable dailyUsages = verifalia .dateFilter(lastThirtyDays) .build()); -for (DailyUsage dailyUsage : dailyUsages) -{ +for (DailyUsage dailyUsage : dailyUsages) { System.out.printf("%s - credit packs: %d, free daily credits: %d", dailyUsage.Date, dailyUsage.CreditPacks, diff --git a/pom.xml b/pom.xml index 2af7402..f0a738e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.verifalia verifalia-java-sdk jar - 2.0.2 + 2.1.0 Verifalia SDK for Java Verifalia provides a simple HTTPS-based API for validating email addresses and checking whether they are deliverable or not. This library allows to easily integrate with Verifalia and verify email addresses in real-time. https://verifalia.com/ @@ -40,6 +40,7 @@ 1.18.4 3.9 4.5.12 + 4.5.12 2.4 UTF-8 UTF-8 @@ -78,6 +79,11 @@ httpclient ${http.client.version} + + org.apache.httpcomponents + httpmime + ${http.mime.version} + net.sf.json-lib diff --git a/src/main/java/com/verifalia/api/VerifaliaRestClient.java b/src/main/java/com/verifalia/api/VerifaliaRestClient.java index 4ea84fe..7993895 100644 --- a/src/main/java/com/verifalia/api/VerifaliaRestClient.java +++ b/src/main/java/com/verifalia/api/VerifaliaRestClient.java @@ -55,7 +55,7 @@ public class VerifaliaRestClient { /** * The default API version supported by the SDK. */ - public static final String DEFAULT_API_VERSION = "v2.1"; + public static final String DEFAULT_API_VERSION = "v2.2"; /** * Cached REST client object. diff --git a/src/main/java/com/verifalia/api/common/serialization/DurationSerializer.java b/src/main/java/com/verifalia/api/common/serialization/DurationSerializer.java index 65e804d..cc2e940 100644 --- a/src/main/java/com/verifalia/api/common/serialization/DurationSerializer.java +++ b/src/main/java/com/verifalia/api/common/serialization/DurationSerializer.java @@ -49,7 +49,9 @@ public class DurationSerializer extends JsonSerializer { @Override public void serialize(Duration value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - if (value != null) { + if (value == null) { + jgen.writeNull(); + } else { jgen.writeString(toString(value)); } } diff --git a/src/main/java/com/verifalia/api/emailvalidations/EmailValidationsRestClient.java b/src/main/java/com/verifalia/api/emailvalidations/EmailValidationsRestClient.java index b9158c3..ebdfe51 100644 --- a/src/main/java/com/verifalia/api/emailvalidations/EmailValidationsRestClient.java +++ b/src/main/java/com/verifalia/api/emailvalidations/EmailValidationsRestClient.java @@ -31,21 +31,13 @@ package com.verifalia.api.emailvalidations; -import com.verifalia.api.common.Direction; -import com.verifalia.api.common.iterables.IterableHelper; -import com.verifalia.api.common.ListingCursor; -import com.verifalia.api.common.Utils; -import com.verifalia.api.common.filters.FilterPredicateFragment; -import com.verifalia.api.common.models.ListSegment; -import com.verifalia.api.common.models.ListSegmentMeta; +import com.verifalia.api.common.*; +import com.verifalia.api.common.filters.*; +import com.verifalia.api.common.iterables.*; +import com.verifalia.api.common.models.*; import com.verifalia.api.emailvalidations.models.*; -import com.verifalia.api.exceptions.InsufficientCreditException; -import com.verifalia.api.exceptions.VerifaliaException; -import com.verifalia.api.exceptions.WaitingInterruptedException; -import com.verifalia.api.rest.HttpRequestMethod; -import com.verifalia.api.rest.RestClient; -import com.verifalia.api.rest.RestRequest; -import com.verifalia.api.rest.RestResponse; +import com.verifalia.api.exceptions.*; +import com.verifalia.api.rest.*; import lombok.Getter; import lombok.NonNull; import lombok.Setter; @@ -53,8 +45,10 @@ import org.apache.commons.lang.NotImplementedException; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.MultipartEntityBuilder; -import java.io.IOException; import java.net.URI; import java.util.HashMap; import java.util.List; @@ -202,7 +196,7 @@ public Validation submit(@NonNull final String[] emailAddresses, @NonNull final * @return A {@link Validation} object representing the submitted email validation job. * @throws VerifaliaException */ - public Validation submit(@NonNull final ValidationRequest validationRequest) throws VerifaliaException { + public Validation submit(@NonNull final AbstractValidationRequest validationRequest) throws VerifaliaException { return submit(validationRequest, null); } @@ -214,20 +208,60 @@ public Validation submit(@NonNull final ValidationRequest validationRequest) thr * @return A {@link Validation} object representing the submitted email validation job. * @throws VerifaliaException */ - public Validation submit(@NonNull final ValidationRequest validationRequest, final WaitingStrategy waitingStrategy) throws VerifaliaException { - // Checks the parameters + public Validation submit(@NonNull final AbstractValidationRequest validationRequest, final WaitingStrategy waitingStrategy) throws VerifaliaException { + // Checks the parameters and build the REST request - if (validationRequest.getEntries() == null) { - throw new IllegalArgumentException("emailAddresses cannot be null"); - } - if (validationRequest.getEntries().size() == 0) { - throw new IllegalArgumentException("Can't validate an empty batch (emailAddresses)"); + RestRequest request; + + if (validationRequest instanceof ValidationRequest) { + ValidationRequest standardValidationRequest = (ValidationRequest) validationRequest; + + if (standardValidationRequest.getEntries() == null) { + throw new IllegalArgumentException("emailAddresses cannot be null"); + } + if (standardValidationRequest.getEntries().size() == 0) { + throw new IllegalArgumentException("Can't validate an empty batch (emailAddresses)"); + } + + request = new RestRequest(HttpRequestMethod.POST, + "email-validations", + // Explicitly set the charset as UTF-8 (see https://github.com/verifalia/verifalia-java-sdk/issues/4) + new StringEntity(RestRequest.serializeToJson(validationRequest), "UTF-8")); } + else if (validationRequest instanceof FileValidationRequest) { + // The actual file content will be checked by the Verifalia API + + FileValidationRequest fileValidationRequest = (FileValidationRequest) validationRequest; + + // Build the multi-part entity + // TODO: Move the entity building part to an ad-hoc class derived from RestRequest + + MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); - // Build the REST request - RestRequest request = new RestRequest(HttpRequestMethod.POST, "email-validations", validationRequest); + // inputFile part + + entityBuilder.addBinaryBody("inputFile", + fileValidationRequest.getInputStream(), + fileValidationRequest.getContentType(), + // HACK: Dummy file name to make the underlying Java multi-part form data serializer happy + "file"); + + // Settings part + + entityBuilder.addTextBody("settings", + RestRequest.serializeToJson(fileValidationRequest), + ContentType.parse("application/json")); + + request = new RestRequest(HttpRequestMethod.POST, + "email-validations", + entityBuilder.build()); + } + else { + throw new IllegalArgumentException("Unsupported class for the validationRequest parameter."); + } // Send the request to the Verifalia servers + RestResponse response = restClient.execute(request); // Handle response based on status code @@ -260,6 +294,10 @@ public Validation submit(@NonNull final ValidationRequest validationRequest, fin throw new InsufficientCreditException(response); } + case HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE: { + throw new UnsupportedMediaTypeException(response); + } + default: { throw new VerifaliaException(response); } diff --git a/src/main/java/com/verifalia/api/emailvalidations/models/AbstractValidationRequest.java b/src/main/java/com/verifalia/api/emailvalidations/models/AbstractValidationRequest.java new file mode 100644 index 0000000..3c2f765 --- /dev/null +++ b/src/main/java/com/verifalia/api/emailvalidations/models/AbstractValidationRequest.java @@ -0,0 +1,100 @@ +/* + * Verifalia - Email list cleaning and real-time email verification service + * https://verifalia.com/ + * support@verifalia.com + * + * Copyright (c) 2005-2020 Cobisi Research + * + * Cobisi Research + * Via Prima Strada, 35 + * 35129, Padova + * Italy - European Union + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.verifalia.api.emailvalidations.models; + +import com.verifalia.api.common.serialization.DurationSerializer; +import com.verifalia.api.emailvalidations.serialization.QualityLevelNameSerializer; +import com.verifalia.api.emailvalidations.serialization.ValidationPrioritySerializer; +import lombok.*; +import org.apache.commons.lang3.StringUtils; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static java.util.Objects.nonNull; + +/** + * Represents the abstract base class for email validation requests to be submitted against the Verifalia API. + */ +@Getter +@Setter +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class AbstractValidationRequest { + private static final Integer VALIDATION_INPUT_PRIORITY_MIN_VALUE = 0; + private static final Integer VALIDATION_INPUT_PRIORITY_MAX_VALUE = 255; + + /** + * An optional user-defined name for the validation job, for your own reference. The name will be returned on + * subsequent API calls and shown on the Verifalia clients area. + */ + private String name; + + /** + * A reference to the expected results quality level for this request. Quality levels determine how Verifalia validates + * email addresses, including whether and how the automatic reprocessing logic occurs (for transient statuses) and the + * verification timeouts settings. + * Use one of {@link QualityLevelName#Standard}, {@link QualityLevelName#High} or {@link QualityLevelName#Extreme} + * values or a custom quality level ID if you have one (custom quality levels are available to premium plans only). + */ + @JsonSerialize(using = QualityLevelNameSerializer.class, include = JsonSerialize.Inclusion.NON_NULL) + private QualityLevelName quality; + + /** + * The strategy Verifalia follows while determining which email addresses are duplicates, within a multiple items job. + * Duplicated items (after the first occurrence) will have the {@link ValidationEntryStatus#Duplicate} status. + */ + private DeduplicationMode deduplication; + + /** + * The eventual priority (speed) of the validation job, relative to the parent Verifalia account. In the event of an account + * with many concurrent validation jobs, this value allows to increase the processing speed of a job with respect to the others. + * The allowed range of values spans from {@link ValidationPriority#Lowest} (0 - lowest priority) to + * {@link ValidationPriority#Highest} (255 - highest priority), where the midway value + * {@link ValidationPriority#Normal} (127) means normal priority; if not specified, Verifalia processes all the + * concurrent validation jobs for an account using the same priority. + */ + @JsonSerialize(using = ValidationPrioritySerializer.class, include = JsonSerialize.Inclusion.NON_NULL) + private ValidationPriority priority; + + /** + * The maximum data retention period Verifalia observes for this verification job, after which the job will be + * automatically deleted. A verification job can be deleted anytime prior to its retention period through the + * {@link com.verifalia.api.emailvalidations.EmailValidationsRestClient#delete(String)} method. + */ + @JsonSerialize(using = DurationSerializer.class, include = JsonSerialize.Inclusion.NON_NULL) + private Duration retention; +} \ No newline at end of file diff --git a/src/main/java/com/verifalia/api/emailvalidations/models/FileValidationRequest.java b/src/main/java/com/verifalia/api/emailvalidations/models/FileValidationRequest.java new file mode 100644 index 0000000..a97256c --- /dev/null +++ b/src/main/java/com/verifalia/api/emailvalidations/models/FileValidationRequest.java @@ -0,0 +1,334 @@ +/* + * Verifalia - Email list cleaning and real-time email verification service + * https://verifalia.com/ + * support@verifalia.com + * + * Copyright (c) 2005-2020 Cobisi Research + * + * Cobisi Research + * Via Prima Strada, 35 + * 35129, Padova + * Italy - European Union + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.verifalia.api.emailvalidations.models; + +import com.verifalia.api.emailvalidations.serialization.LineEndingModeSerializer; +import lombok.*; +import org.apache.http.entity.ContentType; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import java.io.*; + +import static java.util.Objects.nonNull; + +/** + * Represents an email validation request through a file import, to be submitted against the Verifalia API. + * Verifalia offers support for the following file types: + * - plain text files (.txt), with one email address per line (MIME type: text/plain) + * - comma-separated values (.csv), tab-separated values (.tsv) and other delimiter-separated values files (MIME + * types: text/csv and text/tab-separated-values) + * - Microsoft Excel spreadsheets - .xls and .xlsx - (MIME types: application/vnd.ms-excel and + * application/vnd.openxmlformats-officedocument.spreadsheetml.sheet). + */ +@Getter +@Setter +@ToString +@AllArgsConstructor +@Builder +public class FileValidationRequest extends AbstractValidationRequest { + /** + * An {@link InputStream} (a {@link java.io.FileInputStream}, for example) containing the email addresses to validate. + */ + @NonNull + @JsonIgnore + private InputStream inputStream; + + /** + * The {@link ContentType} of the provided input file. + */ + @NonNull + @JsonIgnore + private ContentType contentType; + + /** + * An optional {@link Integer} with the zero-based index of the first row to import and process. If not specified, Verifalia + * will start processing files from the first (0) row. + */ + private Integer startingRow; + + /** + * An optional {@link Integer} with the zero-based index of the last row to import and process. If not specified, Verifalia + * will process rows until the end of the file. + */ + private Integer endingRow; + + /** + * An optional {@link Integer} with the zero-based index of the column to import; applies to comma-separated (.csv), + * tab-separated (.tsv) and other delimiter-separated values files, and Excel files. If not specified, Verifalia will + * use the first (0) column. + */ + private Integer column; + + /** + * An optional {@link Integer} with the zero-based index of the worksheet to import; applies to Excel files only. + * If not specified, Verifalia will use the first (0) worksheet. + */ + private Integer sheet; + + /** + * Allows to specify the line ending sequence of the provided file; applies to plain-text files, comma-separated (.csv), + * tab-separated (.tsv) and other delimiter-separated values files. + */ + @JsonSerialize(using = LineEndingModeSerializer.class, include = JsonSerialize.Inclusion.NON_NULL) + private LineEndingMode lineEnding; + + /** + * An optional string with the column delimiter sequence of the file; applies to comma-separated (.csv), tab-separated + * (.tsv) and other delimiter-separated values files. If not specified, Verifalia will use the , (comma) symbol for + * CSV files and the \t (tab) symbol for TSV files. + */ + private String delimiter; + + // region Constructor overloads accepting a File instance + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param file The file to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + */ + public FileValidationRequest(@NonNull final File file, @NonNull final ContentType contentType) throws FileNotFoundException { + this(file, contentType, null, null); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param file The file to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param quality An optional {@link QualityLevelName} referring to the expected results quality for the request. + */ + public FileValidationRequest(@NonNull final File file, @NonNull final ContentType contentType, final QualityLevelName quality) throws FileNotFoundException { + this(file, contentType, quality, null); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param file The file to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param deduplication An optional {@link DeduplicationMode} to use while determining which email addresses are duplicates. + */ + public FileValidationRequest(@NonNull final File file, @NonNull final ContentType contentType, final DeduplicationMode deduplication) throws FileNotFoundException { + this(file, contentType, null, deduplication); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param file The file to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param quality An optional {@link QualityLevelName} referring to the expected results quality for the request. + * @param deduplication An optional {@link DeduplicationMode} to use while determining which email addresses are duplicates. + */ + public FileValidationRequest(@NonNull final File file, @NonNull final ContentType contentType, final QualityLevelName quality, final DeduplicationMode deduplication) throws FileNotFoundException { + this(new FileInputStream(file), contentType, quality, deduplication); + } + + // endregion + + // region Constructor overloads accepting a file name + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param fileName The name of the file to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + */ + public FileValidationRequest(@NonNull final String fileName, @NonNull final ContentType contentType) throws FileNotFoundException { + this(fileName, contentType, null, null); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param fileName The name of the file to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param quality An optional {@link QualityLevelName} referring to the expected results quality for the request. + */ + public FileValidationRequest(@NonNull final String fileName, @NonNull final ContentType contentType, final QualityLevelName quality) throws FileNotFoundException { + this(fileName, contentType, quality, null); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param fileName The name of the file to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param deduplication An optional {@link DeduplicationMode} to use while determining which email addresses are duplicates. + */ + public FileValidationRequest(@NonNull final String fileName, @NonNull final ContentType contentType, final DeduplicationMode deduplication) throws FileNotFoundException { + this(fileName, contentType, null, deduplication); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param fileName The name of the file to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param quality An optional {@link QualityLevelName} referring to the expected results quality for the request. + * @param deduplication An optional {@link DeduplicationMode} to use while determining which email addresses are duplicates. + */ + public FileValidationRequest(@NonNull final String fileName, @NonNull final ContentType contentType, final QualityLevelName quality, final DeduplicationMode deduplication) throws FileNotFoundException { + this(new File(fileName), contentType, quality, deduplication); + } + + // endregion + + // region Constructor overloads accepting a file name and a MIME type + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param fileName The name of the file to be submitted for validation. + * @param mimeType The MIME content type of the file to be submitted for validation. + */ + public FileValidationRequest(@NonNull final String fileName, @NonNull final String mimeType) throws FileNotFoundException { + this(fileName, mimeType, null, null); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param fileName The name of the file to be submitted for validation. + * @param mimeType The MIME content type of the file to be submitted for validation. + * @param quality An optional {@link QualityLevelName} referring to the expected results quality for the request. + */ + public FileValidationRequest(@NonNull final String fileName, @NonNull final String mimeType, final QualityLevelName quality) throws FileNotFoundException { + this(fileName, mimeType, quality, null); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param fileName The name of the file to be submitted for validation. + * @param mimeType The MIME content type of the file to be submitted for validation. + * @param deduplication An optional {@link DeduplicationMode} to use while determining which email addresses are duplicates. + */ + public FileValidationRequest(@NonNull final String fileName, @NonNull final String mimeType, final DeduplicationMode deduplication) throws FileNotFoundException { + this(fileName, mimeType, null, deduplication); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param fileName The name of the file to be submitted for validation. + * @param mimeType The MIME content type of the file to be submitted for validation. + * @param quality An optional {@link QualityLevelName} referring to the expected results quality for the request. + * @param deduplication An optional {@link DeduplicationMode} to use while determining which email addresses are duplicates. + */ + public FileValidationRequest(@NonNull final String fileName, @NonNull String mimeType, final QualityLevelName quality, final DeduplicationMode deduplication) throws FileNotFoundException { + this(new File(fileName), ContentType.create(mimeType), quality, deduplication); + } + + // endregion + + // region Constructor overloads accepting a byte array + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param data The file byte array to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + */ + public FileValidationRequest(@NonNull final byte[] data, @NonNull final ContentType contentType) { + this(data, contentType, null, null); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param data The file byte array to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param quality An optional {@link QualityLevelName} referring to the expected results quality for the request. + */ + public FileValidationRequest(@NonNull final byte[] data, @NonNull final ContentType contentType, final QualityLevelName quality) { + this(data, contentType, quality, null); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param data The file byte array to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param deduplication An optional {@link DeduplicationMode} to use while determining which email addresses are duplicates. + */ + public FileValidationRequest(@NonNull final byte[] data, @NonNull final ContentType contentType, final DeduplicationMode deduplication) { + this(data, contentType, null, deduplication); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param data The file byte array to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param quality An optional {@link QualityLevelName} referring to the expected results quality for the request. + * @param deduplication An optional {@link DeduplicationMode} to use while determining which email addresses are duplicates. + */ + public FileValidationRequest(@NonNull final byte[] data, @NonNull final ContentType contentType, final QualityLevelName quality, final DeduplicationMode deduplication) { + this(new ByteArrayInputStream(data), contentType, deduplication); + } + + // endregion + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param stream The input stream to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + */ + public FileValidationRequest(@NonNull final InputStream stream, @NonNull final ContentType contentType) { + this(stream, contentType, null, null); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param stream The input stream to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param quality An optional {@link QualityLevelName} referring to the expected results quality for the request. + */ + public FileValidationRequest(@NonNull final InputStream stream, @NonNull final ContentType contentType, final QualityLevelName quality) { + this(stream, contentType, quality, null); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param stream The input stream to be submitted for validation. + * @param contentType The {@link ContentType} of the file to be submitted for validation. + * @param deduplication An optional {@link DeduplicationMode} to use while determining which email addresses are duplicates. + */ + public FileValidationRequest(@NonNull final InputStream stream, @NonNull final ContentType contentType, final DeduplicationMode deduplication) { + this(stream, contentType, null, deduplication); + } + + /** + * Initializes a {@link FileValidationRequest} to be submitted to the Verifalia email validation engine. + * @param stream The input stream to be submitted for validation. + * @param quality An optional {@link QualityLevelName} referring to the expected results quality for the request. + * @param deduplication An optional {@link DeduplicationMode} to use while determining which email addresses are duplicates. + */ + public FileValidationRequest(@NonNull final InputStream stream, @NonNull final ContentType contentType, final QualityLevelName quality, final DeduplicationMode deduplication) { + setInputStream(stream); + setContentType(contentType); + + if (nonNull(quality)) { + setQuality(quality); + } + if (nonNull(deduplication)) { + setDeduplication(deduplication); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/verifalia/api/emailvalidations/models/LineEndingMode.java b/src/main/java/com/verifalia/api/emailvalidations/models/LineEndingMode.java new file mode 100644 index 0000000..b96ed00 --- /dev/null +++ b/src/main/java/com/verifalia/api/emailvalidations/models/LineEndingMode.java @@ -0,0 +1,26 @@ +package com.verifalia.api.emailvalidations.models; + +/** + * The line-ending mode for an input text file provided to the Verifalia API for verification. + */ +public enum LineEndingMode { + /** + * Automatic line-ending detection, attempts to guess the correct line ending from the first chunk of data. + */ + Auto, + + /** + * CR + LF sequence (\r\n), commonly used in files generated on Windows. + */ + CrLf, + + /** + * CR sequence (\r), commonly used in files generated on classic MacOS. + */ + Cr, + + /** + * LF (\n), commonly used in files generated on Unix and Unix-like systems (including Linux and MacOS). + */ + Lf +} diff --git a/src/main/java/com/verifalia/api/emailvalidations/models/ValidationRequest.java b/src/main/java/com/verifalia/api/emailvalidations/models/ValidationRequest.java index c86c54c..a0722d3 100644 --- a/src/main/java/com/verifalia/api/emailvalidations/models/ValidationRequest.java +++ b/src/main/java/com/verifalia/api/emailvalidations/models/ValidationRequest.java @@ -56,57 +56,13 @@ @NoArgsConstructor @AllArgsConstructor @Builder -public class ValidationRequest { - private static final Integer VALIDATION_INPUT_PRIORITY_MIN_VALUE = 0; - private static final Integer VALIDATION_INPUT_PRIORITY_MAX_VALUE = 255; - - /** - * An optional user-defined name for the validation job, for your own reference. The name will be returned on - * subsequent API calls and shown on the Verifalia clients area. - */ - private String name; - +public class ValidationRequest extends AbstractValidationRequest { /** * One or more {@link ValidationEntry} containing with the email addresses to validate, each along with an optional * custom state to be passed back upon completion. */ private List entries; - /** - * A reference to the expected results quality level for this request. Quality levels determine how Verifalia validates - * email addresses, including whether and how the automatic reprocessing logic occurs (for transient statuses) and the - * verification timeouts settings. - * Use one of {@link QualityLevelName#Standard}, {@link QualityLevelName#High} or {@link QualityLevelName#Extreme} - * values or a custom quality level ID if you have one (custom quality levels are available to premium plans only). - */ - @JsonSerialize(using = QualityLevelNameSerializer.class) - private QualityLevelName quality; - - /** - * The strategy Verifalia follows while determining which email addresses are duplicates, within a multiple items job. - * Duplicated items (after the first occurrence) will have the {@link ValidationEntryStatus#Duplicate} status. - */ - private DeduplicationMode deduplication; - - /** - * The eventual priority (speed) of the validation job, relative to the parent Verifalia account. In the event of an account - * with many concurrent validation jobs, this value allows to increase the processing speed of a job with respect to the others. - * The allowed range of values spans from {@link ValidationPriority#Lowest} (0 - lowest priority) to - * {@link ValidationPriority#Highest} (255 - highest priority), where the midway value - * {@link ValidationPriority#Normal} (127) means normal priority; if not specified, Verifalia processes all the - * concurrent validation jobs for an account using the same priority. - */ - @JsonSerialize(using = ValidationPrioritySerializer.class) - private ValidationPriority priority; - - /** - * The maximum data retention period Verifalia observes for this verification job, after which the job will be - * automatically deleted. A verification job can be deleted anytime prior to its retention period through the - * {@link com.verifalia.api.emailvalidations.EmailValidationsRestClient#delete(String)} method. - */ - @JsonSerialize(using = DurationSerializer.class) - private Duration retention; - /** * Initializes a {@link ValidationRequest} to be submitted to the Verifalia email validation engine. * @param emailAddress The email address to validate. diff --git a/src/main/java/com/verifalia/api/emailvalidations/serialization/LineEndingModeSerializer.java b/src/main/java/com/verifalia/api/emailvalidations/serialization/LineEndingModeSerializer.java new file mode 100644 index 0000000..23a3520 --- /dev/null +++ b/src/main/java/com/verifalia/api/emailvalidations/serialization/LineEndingModeSerializer.java @@ -0,0 +1,53 @@ +/* + * Verifalia - Email list cleaning and real-time email verification service + * https://verifalia.com/ + * support@verifalia.com + * + * Copyright (c) 2005-2020 Cobisi Research + * + * Cobisi Research + * Via Prima Strada, 35 + * 35129, Padova + * Italy - European Union + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.verifalia.api.emailvalidations.serialization; + +import com.verifalia.api.emailvalidations.models.LineEndingMode; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; + +import java.io.IOException; + +/** + * A Json serializer for the line ending modes accepted by the Verifalia API. + */ +public class LineEndingModeSerializer extends JsonSerializer { + @Override + public void serialize(LineEndingMode value, JsonGenerator jgen, SerializerProvider provider) throws IOException { + if (value == null || value == LineEndingMode.Auto) { + jgen.writeNull(); + } else { + jgen.writeString(value.toString()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/verifalia/api/emailvalidations/serialization/QualityLevelNameSerializer.java b/src/main/java/com/verifalia/api/emailvalidations/serialization/QualityLevelNameSerializer.java index 232a380..b81bd19 100644 --- a/src/main/java/com/verifalia/api/emailvalidations/serialization/QualityLevelNameSerializer.java +++ b/src/main/java/com/verifalia/api/emailvalidations/serialization/QualityLevelNameSerializer.java @@ -44,7 +44,9 @@ public class QualityLevelNameSerializer extends JsonSerializer { @Override public void serialize(QualityLevelName value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - if (value != null) { + if (value == null) { + jgen.writeNull(); + } else { jgen.writeString(value.toString()); } } diff --git a/src/main/java/com/verifalia/api/emailvalidations/serialization/ValidationPrioritySerializer.java b/src/main/java/com/verifalia/api/emailvalidations/serialization/ValidationPrioritySerializer.java index 506b209..b8f4df1 100644 --- a/src/main/java/com/verifalia/api/emailvalidations/serialization/ValidationPrioritySerializer.java +++ b/src/main/java/com/verifalia/api/emailvalidations/serialization/ValidationPrioritySerializer.java @@ -45,7 +45,9 @@ public class ValidationPrioritySerializer extends JsonSerializer { @Override public void serialize(ValidationPriority value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - if (value != null) { + if (value == null || value == ValidationPriority.Normal) { + jgen.writeNull(); + } else { jgen.writeString(new Byte(value.getValue()).toString()); } } diff --git a/src/main/java/com/verifalia/api/exceptions/UnsupportedMediaTypeException.java b/src/main/java/com/verifalia/api/exceptions/UnsupportedMediaTypeException.java new file mode 100644 index 0000000..46a0db1 --- /dev/null +++ b/src/main/java/com/verifalia/api/exceptions/UnsupportedMediaTypeException.java @@ -0,0 +1,47 @@ +/* + * Verifalia - Email list cleaning and real-time email verification service + * https://verifalia.com/ + * support@verifalia.com + * + * Copyright (c) 2005-2020 Cobisi Research + * + * Cobisi Research + * Via Prima Strada, 35 + * 35129, Padova + * Italy - European Union + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * + */ +package com.verifalia.api.exceptions; + +import com.verifalia.api.credits.CreditsRestClient; +import com.verifalia.api.rest.RestResponse; + +/** + * The exception that is thrown whenever Verifalia can't process the format of the provided file. + */ +public class UnsupportedMediaTypeException extends VerifaliaException { + public UnsupportedMediaTypeException(RestResponse response) { + super(response); + } +} \ No newline at end of file diff --git a/src/main/java/com/verifalia/api/rest/RestClient.java b/src/main/java/com/verifalia/api/rest/RestClient.java index 557e2c4..7725426 100644 --- a/src/main/java/com/verifalia/api/rest/RestClient.java +++ b/src/main/java/com/verifalia/api/rest/RestClient.java @@ -127,49 +127,27 @@ class EndpointServerError { private CloseableHttpResponse sendRequest(@NonNull final URI baseURI, @NonNull final RestRequest restRequest, @NonNull final AuthenticationProvider authenticationProviderOverride) throws VerifaliaException, IOException { - StringBuilder sb = new StringBuilder(); - sb.append(baseURI.toString()).append("/").append(apiVersion).append("/").append(restRequest.getResource()); + // Determine the intermediate URI, including the API version, for this invocation - URI uri; + StringBuilder sbApiVersionURI = new StringBuilder(); + sbApiVersionURI.append(baseURI.toString()).append("/").append(apiVersion).append("/"); + + URI apiVersionURI; try { - uri = new URI(sb.toString()); + apiVersionURI = new URI(sbApiVersionURI.toString()); } catch (URISyntaxException e) { - throw new IOException("Invalid URI " + sb); + throw new IOException("Invalid URI " + sbApiVersionURI); } - CloseableHttpClient client = authenticationProviderOverride.buildClient(this); - HttpRequestBase request; - - switch (restRequest.getMethod()) { - case GET: { - request = new HttpGet(uri); - break; - } - - case POST: { - request = new HttpPost(uri); - StringEntity entity = new StringEntity(restRequest.getData()); - ((HttpPost) request).setEntity(entity); - break; - } + // Build the HTTP client and the HTTP request out of the provided RestRequest - case DELETE: { - request = new HttpDelete(uri); - break; - } - - default: - throw new IllegalArgumentException("Unsupported method " + restRequest.getMethod()); - } + CloseableHttpClient client = authenticationProviderOverride.buildClient(this); + HttpRequestBase request = restRequest.buildHttpRequest(apiVersionURI); // Common headers and authentication handling request.setHeader(HttpHeaders.USER_AGENT, this.userAgent); - request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); - request.setHeader(HttpHeaders.ACCEPT, "application/json"); - request.setHeader(HttpHeaders.ACCEPT_ENCODING, "gzip"); - authenticationProviderOverride.decorateRequest(this, request); return client.execute(request); diff --git a/src/main/java/com/verifalia/api/rest/RestRequest.java b/src/main/java/com/verifalia/api/rest/RestRequest.java index f68e811..cac779e 100644 --- a/src/main/java/com/verifalia/api/rest/RestRequest.java +++ b/src/main/java/com/verifalia/api/rest/RestRequest.java @@ -34,11 +34,20 @@ import lombok.Getter; import lombok.NonNull; import lombok.Setter; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHeaders; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.AbstractHttpEntity; +import org.apache.http.entity.StringEntity; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.annotate.JsonSerialize; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; /** * Represents a REST request. @@ -46,49 +55,106 @@ @Getter @Setter public class RestRequest { - /** - * Base URI + * HTTP request data, if any. */ - private URI baseURI; + private HttpEntity httpEntity; /** - * HTTP request method + * HTTP request method. */ + @NonNull private HttpRequestMethod method; /** - * Request target resource + * Request target resource. */ + @NonNull private String resource; - /** - * HTTP request data - */ - private String data; + public static String serializeToJson(Object data) { + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL); + return mapper.writeValueAsString(data); + } catch (IOException exception) { + throw new IllegalArgumentException("Cannot convert the payload into a JSON string.", exception); + } + } - /** - * Constructs new object for a given resource with given method - */ public RestRequest(@NonNull final HttpRequestMethod method, @NonNull final String resource) { - this(method, resource, null); + this.setMethod(method); + this.setResource(resource); } - /** - * Constructs new object for a given resource with given method and given data - */ - public RestRequest(@NonNull final HttpRequestMethod method, @NonNull final String resource, final Object data) { - this.method = method; - this.resource = resource; - - if (data != null) { - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL); - this.data = mapper.writeValueAsString(data); - } catch (IOException exception) { - throw new IllegalArgumentException("Cannot convert the payload into a JSON string.", exception); + public RestRequest(@NonNull final HttpRequestMethod method, @NonNull final String resource, @NonNull final HttpEntity httpEntity) { + this(method, resource); + this.setHttpEntity(httpEntity); + } + + public HttpRequestBase buildHttpRequest(@NonNull URI apiVersionURI) throws IOException { + HttpRequestBase request; + + // Determine the final URI for this request + + URI requestURI = buildRequestURI(apiVersionURI); + + // Build the actual HTTP request + + switch (getMethod()) { + case GET: { + request = new HttpGet(requestURI); + break; + } + + case POST: { + request = new HttpPost(requestURI); + ((HttpPost) request).setEntity(httpEntity); + + if (httpEntity != null) { + // HACK: Since MultipartFormEntity is not public (WTF!), we will assume that all entities are multi-parts + // *unless* they are instances of a specific defined type. + + if (httpEntity instanceof StringEntity) { + request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + } + else { + request.setHeader(HttpHeaders.CONTENT_TYPE, httpEntity.getContentType().getValue()); + } + } + + break; } + + case DELETE: { + request = new HttpDelete(requestURI); + break; + } + + default: + throw new IllegalArgumentException("Unsupported method " + getMethod()); + } + + // Common headers + + request.setHeader(HttpHeaders.ACCEPT, "application/json"); + request.setHeader(HttpHeaders.ACCEPT_ENCODING, "gzip"); + + return request; + } + + protected URI buildRequestURI(URI apiVersionURI) throws IOException { + // Determine the final URI for this request + + URI requestURI; + String requestURICandidate = apiVersionURI.toString() + getResource(); + + try { + requestURI = new URI(requestURICandidate); + } catch (URISyntaxException e) { + throw new IOException("Invalid URI " + requestURICandidate); } + + return requestURI; } } \ No newline at end of file diff --git a/src/main/java/com/verifalia/api/rest/WellKnownMimeTypes.java b/src/main/java/com/verifalia/api/rest/WellKnownMimeTypes.java new file mode 100644 index 0000000..3721c66 --- /dev/null +++ b/src/main/java/com/verifalia/api/rest/WellKnownMimeTypes.java @@ -0,0 +1,31 @@ +package com.verifalia.api.rest; + +/** + * Contains the MIME content types supported by the Verifalia API. + */ +public final class WellKnownMimeTypes { + /** + * Plain-text files (.txt), with one email address per line. + */ + public static final String TEXT_PLAIN = "text/plain"; + + /** + * Comma-separated values (.csv). + */ + public static final String TEXT_CSV = "text/csv"; + + /** + * Tab-separated values (usually coming with the .tsv extension). + */ + public static final String TEXT_TSV = "text/tab-separated-values"; + + /** + * Microsoft Excel 97-2003 Worksheet (.xls). + */ + public static final String EXCEL_XLS = "application/vnd.ms-excel"; + + /** + * Microsoft Excel workbook (.xslx). + */ + public static final String EXCEL_XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; +} diff --git a/src/main/java/com/verifalia/api/rest/security/BearerAuthenticationProvider.java b/src/main/java/com/verifalia/api/rest/security/BearerAuthenticationProvider.java index 7cc3fa9..c937646 100644 --- a/src/main/java/com/verifalia/api/rest/security/BearerAuthenticationProvider.java +++ b/src/main/java/com/verifalia/api/rest/security/BearerAuthenticationProvider.java @@ -42,6 +42,8 @@ import net.sf.json.JSONObject; import org.apache.http.HttpHeaders; import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; /** * Allows to authenticate a REST client against the Verifalia API using bearer authentication. @@ -72,7 +74,10 @@ private static String getBearerToken(RestClient client, String username, String credentials.setPassword(password); // Make rest request - RestRequest request = new RestRequest(HttpRequestMethod.POST, "auth/tokens", credentials); + + RestRequest request = new RestRequest(HttpRequestMethod.POST, + "auth/tokens", + new StringEntity(RestRequest.serializeToJson(credentials), "UTF-8")); // Sends the request to the Verifalia servers RestResponse response = client.execute(request, new AuthenticationProvider() { });