requestHandlers) {
+ requestHandlers.add(new ConcatenationOptionsRequestHandler());
+ requestHandlers.add(new ConcatenationPostRequestHandler());
+ requestHandlers.add(new ConcatenationHeadRequestHandler());
+ }
}
diff --git a/src/main/java/me/desair/tus/server/concatenation/ConcatenationHeadRequestHandler.java b/src/main/java/me/desair/tus/server/concatenation/ConcatenationHeadRequestHandler.java
index ab1bb9c..5f7cabc 100644
--- a/src/main/java/me/desair/tus/server/concatenation/ConcatenationHeadRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/concatenation/ConcatenationHeadRequestHandler.java
@@ -2,7 +2,6 @@
import java.io.IOException;
import java.util.Objects;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.TusException;
@@ -14,46 +13,53 @@
import me.desair.tus.server.util.TusServletResponse;
/**
- * The response to a HEAD request for a upload SHOULD NOT contain the Upload-Offset header unless the
- * concatenation has been successfully finished. After successful concatenation, the Upload-Offset and
- * Upload-Length MUST be set and their values MUST be equal. The value of the Upload-Offset header before
- * concatenation is not defined for a upload.
- *
- * The response to a HEAD request for a partial upload MUST contain the Upload-Offset header. Response to HEAD
- * request against partial or upload MUST include the Upload-Concat header and its value as received in
- * the upload creation request.
+ * The response to a HEAD request for a upload SHOULD NOT contain the Upload-Offset header unless
+ * the concatenation has been successfully finished. After successful concatenation, the
+ * Upload-Offset and Upload-Length MUST be set and their values MUST be equal. The value of the
+ * Upload-Offset header before concatenation is not defined for a upload.
+ *
+ * The response to a HEAD request for a partial upload MUST contain the Upload-Offset header.
+ * Response to HEAD request against partial or upload MUST include the Upload-Concat header and its
+ * value as received in the upload creation request.
*/
public class ConcatenationHeadRequestHandler extends AbstractRequestHandler {
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.HEAD.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.HEAD.equals(method);
+ }
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException, TusException {
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
+ UploadInfo uploadInfo =
+ uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
- if (!UploadType.REGULAR.equals(uploadInfo.getUploadType())) {
- servletResponse.setHeader(HttpHeader.UPLOAD_CONCAT, uploadInfo.getUploadConcatHeaderValue());
- }
+ if (!UploadType.REGULAR.equals(uploadInfo.getUploadType())) {
+ servletResponse.setHeader(HttpHeader.UPLOAD_CONCAT, uploadInfo.getUploadConcatHeaderValue());
+ }
- if (UploadType.CONCATENATED.equals(uploadInfo.getUploadType())) {
- if (uploadInfo.isUploadInProgress()) {
- //Execute the merge function again to update our upload data
- uploadStorageService.getUploadConcatenationService().merge(uploadInfo);
- }
+ if (UploadType.CONCATENATED.equals(uploadInfo.getUploadType())) {
+ if (uploadInfo.isUploadInProgress()) {
+ // Execute the merge function again to update our upload data
+ uploadStorageService.getUploadConcatenationService().merge(uploadInfo);
+ }
- if (uploadInfo.hasLength()) {
- servletResponse.setHeader(HttpHeader.UPLOAD_LENGTH, Objects.toString(uploadInfo.getLength()));
- }
+ if (uploadInfo.hasLength()) {
+ servletResponse.setHeader(
+ HttpHeader.UPLOAD_LENGTH, Objects.toString(uploadInfo.getLength()));
+ }
- if (!uploadInfo.isUploadInProgress()) {
- servletResponse.setHeader(HttpHeader.UPLOAD_OFFSET, Objects.toString(uploadInfo.getOffset()));
- }
- }
+ if (!uploadInfo.isUploadInProgress()) {
+ servletResponse.setHeader(
+ HttpHeader.UPLOAD_OFFSET, Objects.toString(uploadInfo.getOffset()));
+ }
}
+ }
}
diff --git a/src/main/java/me/desair/tus/server/concatenation/ConcatenationOptionsRequestHandler.java b/src/main/java/me/desair/tus/server/concatenation/ConcatenationOptionsRequestHandler.java
index 515d463..979c39e 100644
--- a/src/main/java/me/desair/tus/server/concatenation/ConcatenationOptionsRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/concatenation/ConcatenationOptionsRequestHandler.java
@@ -3,17 +3,16 @@
import me.desair.tus.server.util.AbstractExtensionRequestHandler;
/**
- * If the Server supports this extension, it MUST add concatenation to the Tus-Extension header.
- * The Client MAY send the concatenation request while the partial uploads are still in progress.
- * This feature MUST be explicitly announced by the Server by adding concatenation-unfinished to
- * the Tus-Extension header.
+ * If the Server supports this extension, it MUST add concatenation to the Tus-Extension header. The
+ * Client MAY send the concatenation request while the partial uploads are still in progress. This
+ * feature MUST be explicitly announced by the Server by adding concatenation-unfinished to the
+ * Tus-Extension header.
*/
public class ConcatenationOptionsRequestHandler extends AbstractExtensionRequestHandler {
- @Override
- protected void appendExtensions(StringBuilder extensionBuilder) {
- addExtension(extensionBuilder, "concatenation");
- addExtension(extensionBuilder, "concatenation-unfinished");
- }
-
+ @Override
+ protected void appendExtensions(StringBuilder extensionBuilder) {
+ addExtension(extensionBuilder, "concatenation");
+ addExtension(extensionBuilder, "concatenation-unfinished");
+ }
}
diff --git a/src/main/java/me/desair/tus/server/concatenation/ConcatenationPostRequestHandler.java b/src/main/java/me/desair/tus/server/concatenation/ConcatenationPostRequestHandler.java
index cc32eb1..9b96a6e 100644
--- a/src/main/java/me/desair/tus/server/concatenation/ConcatenationPostRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/concatenation/ConcatenationPostRequestHandler.java
@@ -1,7 +1,6 @@
package me.desair.tus.server.concatenation;
import java.io.IOException;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.TusException;
@@ -15,46 +14,52 @@
import org.apache.commons.lang3.StringUtils;
/**
- * The Server MUST acknowledge a successful upload creation with the 201 Created status.
- * The Server MUST set the Location header to the URL of the created resource. This URL MAY be absolute or relative.
+ * The Server MUST acknowledge a successful upload creation with the 201 Created status. The Server
+ * MUST set the Location header to the URL of the created resource. This URL MAY be absolute or
+ * relative.
*/
public class ConcatenationPostRequestHandler extends AbstractRequestHandler {
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.POST.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.POST.equals(method);
+ }
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException, TusException {
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
- //For post requests, the upload URI is part of the response
- String uploadUri = servletResponse.getHeader(HttpHeader.LOCATION);
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(uploadUri, ownerKey);
+ // For post requests, the upload URI is part of the response
+ String uploadUri = servletResponse.getHeader(HttpHeader.LOCATION);
+ UploadInfo uploadInfo = uploadStorageService.getUploadInfo(uploadUri, ownerKey);
- if (uploadInfo != null) {
+ if (uploadInfo != null) {
- String uploadConcatValue = servletRequest.getHeader(HttpHeader.UPLOAD_CONCAT);
- if (StringUtils.equalsIgnoreCase(uploadConcatValue, "partial")) {
- uploadInfo.setUploadType(UploadType.PARTIAL);
+ String uploadConcatValue = servletRequest.getHeader(HttpHeader.UPLOAD_CONCAT);
+ if (StringUtils.equalsIgnoreCase(uploadConcatValue, "partial")) {
+ uploadInfo.setUploadType(UploadType.PARTIAL);
- } else if (StringUtils.startsWithIgnoreCase(uploadConcatValue, "final")) {
- //reset the length, just to be sure
- uploadInfo.setLength(null);
- uploadInfo.setUploadType(UploadType.CONCATENATED);
- uploadInfo.setConcatenationPartIds(Utils.parseConcatenationIDsFromHeader(uploadConcatValue));
+ } else if (StringUtils.startsWithIgnoreCase(uploadConcatValue, "final")) {
+ // reset the length, just to be sure
+ uploadInfo.setLength(null);
+ uploadInfo.setUploadType(UploadType.CONCATENATED);
+ uploadInfo.setConcatenationPartIds(
+ Utils.parseConcatenationIDsFromHeader(uploadConcatValue));
- uploadStorageService.getUploadConcatenationService().merge(uploadInfo);
+ uploadStorageService.getUploadConcatenationService().merge(uploadInfo);
- } else {
- uploadInfo.setUploadType(UploadType.REGULAR);
- }
+ } else {
+ uploadInfo.setUploadType(UploadType.REGULAR);
+ }
- uploadInfo.setUploadConcatHeaderValue(uploadConcatValue);
+ uploadInfo.setUploadConcatHeaderValue(uploadConcatValue);
- uploadStorageService.update(uploadInfo);
- }
+ uploadStorageService.update(uploadInfo);
}
+ }
}
diff --git a/src/main/java/me/desair/tus/server/concatenation/validation/NoUploadLengthOnFinalValidator.java b/src/main/java/me/desair/tus/server/concatenation/validation/NoUploadLengthOnFinalValidator.java
index 16dee6b..69e10ab 100644
--- a/src/main/java/me/desair/tus/server/concatenation/validation/NoUploadLengthOnFinalValidator.java
+++ b/src/main/java/me/desair/tus/server/concatenation/validation/NoUploadLengthOnFinalValidator.java
@@ -1,8 +1,7 @@
package me.desair.tus.server.concatenation.validation;
-import java.io.IOException;
import jakarta.servlet.http.HttpServletRequest;
-
+import java.io.IOException;
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
@@ -11,28 +10,29 @@
import me.desair.tus.server.upload.UploadStorageService;
import org.apache.commons.lang3.StringUtils;
-/**
- * The Client MUST NOT include the Upload-Length header in the upload creation.
- */
+/** The Client MUST NOT include the Upload-Length header in the upload creation. */
public class NoUploadLengthOnFinalValidator implements RequestValidator {
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws IOException, TusException {
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
- String uploadConcatValue = request.getHeader(HttpHeader.UPLOAD_CONCAT);
+ String uploadConcatValue = request.getHeader(HttpHeader.UPLOAD_CONCAT);
- if (StringUtils.startsWithIgnoreCase(uploadConcatValue, "final")
- && StringUtils.isNotBlank(request.getHeader(HttpHeader.UPLOAD_LENGTH))) {
+ if (StringUtils.startsWithIgnoreCase(uploadConcatValue, "final")
+ && StringUtils.isNotBlank(request.getHeader(HttpHeader.UPLOAD_LENGTH))) {
- throw new UploadLengthNotAllowedOnConcatenationException(
- "The upload length of a concatenated upload cannot be set");
- }
+ throw new UploadLengthNotAllowedOnConcatenationException(
+ "The upload length of a concatenated upload cannot be set");
}
+ }
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.POST.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.POST.equals(method);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/concatenation/validation/PartialUploadsExistValidator.java b/src/main/java/me/desair/tus/server/concatenation/validation/PartialUploadsExistValidator.java
index dada748..a0f40df 100644
--- a/src/main/java/me/desair/tus/server/concatenation/validation/PartialUploadsExistValidator.java
+++ b/src/main/java/me/desair/tus/server/concatenation/validation/PartialUploadsExistValidator.java
@@ -1,8 +1,7 @@
package me.desair.tus.server.concatenation.validation;
-import java.io.IOException;
import jakarta.servlet.http.HttpServletRequest;
-
+import java.io.IOException;
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
@@ -13,34 +12,36 @@
import me.desair.tus.server.util.Utils;
import org.apache.commons.lang3.StringUtils;
-/**
- * Validate that the IDs specified in the Upload-Concat header map to an existing upload
- */
+/** Validate that the IDs specified in the Upload-Concat header map to an existing upload */
public class PartialUploadsExistValidator implements RequestValidator {
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws IOException, TusException {
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
- String uploadConcatValue = request.getHeader(HttpHeader.UPLOAD_CONCAT);
+ String uploadConcatValue = request.getHeader(HttpHeader.UPLOAD_CONCAT);
- if (StringUtils.startsWithIgnoreCase(uploadConcatValue, "final")) {
+ if (StringUtils.startsWithIgnoreCase(uploadConcatValue, "final")) {
- for (String uploadUri : Utils.parseConcatenationIDsFromHeader(uploadConcatValue)) {
+ for (String uploadUri : Utils.parseConcatenationIDsFromHeader(uploadConcatValue)) {
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(uploadUri, ownerKey);
- if (uploadInfo == null) {
- throw new InvalidPartialUploadIdException("The URI " + uploadUri
- + " in Upload-Concat header does not match an existing upload");
- }
- }
+ UploadInfo uploadInfo = uploadStorageService.getUploadInfo(uploadUri, ownerKey);
+ if (uploadInfo == null) {
+ throw new InvalidPartialUploadIdException(
+ "The URI "
+ + uploadUri
+ + " in Upload-Concat header does not match an existing upload");
}
+ }
}
+ }
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.POST.equals(method);
- }
-
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.POST.equals(method);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/concatenation/validation/PatchFinalUploadValidator.java b/src/main/java/me/desair/tus/server/concatenation/validation/PatchFinalUploadValidator.java
index 3ea1bd4..a55328b 100644
--- a/src/main/java/me/desair/tus/server/concatenation/validation/PatchFinalUploadValidator.java
+++ b/src/main/java/me/desair/tus/server/concatenation/validation/PatchFinalUploadValidator.java
@@ -1,8 +1,7 @@
package me.desair.tus.server.concatenation.validation;
-import java.io.IOException;
import jakarta.servlet.http.HttpServletRequest;
-
+import java.io.IOException;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
import me.desair.tus.server.exception.PatchOnFinalUploadNotAllowedException;
@@ -12,26 +11,29 @@
import me.desair.tus.server.upload.UploadType;
/**
- * The Server MUST respond with the 403 Forbidden status to PATCH requests against a upload URL
- * and MUST NOT modify the or its partial uploads.
+ * The Server MUST respond with the 403 Forbidden status to PATCH requests against a upload URL and
+ * MUST NOT modify the or its partial uploads.
*/
public class PatchFinalUploadValidator implements RequestValidator {
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws IOException, TusException {
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(request.getRequestURI(), ownerKey);
+ UploadInfo uploadInfo = uploadStorageService.getUploadInfo(request.getRequestURI(), ownerKey);
- if (uploadInfo != null && UploadType.CONCATENATED.equals(uploadInfo.getUploadType())) {
- throw new PatchOnFinalUploadNotAllowedException("You cannot send a PATCH request for a "
- + "concatenated upload URI");
- }
+ if (uploadInfo != null && UploadType.CONCATENATED.equals(uploadInfo.getUploadType())) {
+ throw new PatchOnFinalUploadNotAllowedException(
+ "You cannot send a PATCH request for a " + "concatenated upload URI");
}
+ }
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.PATCH.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.PATCH.equals(method);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/CoreDefaultResponseHeadersHandler.java b/src/main/java/me/desair/tus/server/core/CoreDefaultResponseHeadersHandler.java
index 27a79bc..1e19a73 100644
--- a/src/main/java/me/desair/tus/server/core/CoreDefaultResponseHeadersHandler.java
+++ b/src/main/java/me/desair/tus/server/core/CoreDefaultResponseHeadersHandler.java
@@ -9,29 +9,32 @@
import me.desair.tus.server.util.TusServletResponse;
/**
- * The Tus-Resumable header MUST be included in every request and response except for OPTIONS requests.
- * The value MUST be the version of the protocol used by the Client or the Server.
+ * The Tus-Resumable header MUST be included in every request and response except for OPTIONS
+ * requests. The value MUST be the version of the protocol used by the Client or the Server.
*/
public class CoreDefaultResponseHeadersHandler implements RequestHandler {
- @Override
- public boolean supports(HttpMethod method) {
- return true;
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return true;
+ }
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) {
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey) {
- //Always set Tus-Resumable header
- servletResponse.setHeader(HttpHeader.TUS_RESUMABLE, TusFileUploadService.TUS_API_VERSION);
- //By default, set the Content-Length to 0
- servletResponse.setHeader(HttpHeader.CONTENT_LENGTH, "0");
- }
+ // Always set Tus-Resumable header
+ servletResponse.setHeader(HttpHeader.TUS_RESUMABLE, TusFileUploadService.TUS_API_VERSION);
+ // By default, set the Content-Length to 0
+ servletResponse.setHeader(HttpHeader.CONTENT_LENGTH, "0");
+ }
- @Override
- public boolean isErrorHandler() {
- return true;
- }
+ @Override
+ public boolean isErrorHandler() {
+ return true;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/CoreHeadRequestHandler.java b/src/main/java/me/desair/tus/server/core/CoreHeadRequestHandler.java
index 33bbd48..416cbef 100644
--- a/src/main/java/me/desair/tus/server/core/CoreHeadRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/core/CoreHeadRequestHandler.java
@@ -1,9 +1,8 @@
package me.desair.tus.server.core;
+import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
-import jakarta.servlet.http.HttpServletResponse;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.upload.UploadInfo;
@@ -13,39 +12,46 @@
import me.desair.tus.server.util.TusServletRequest;
import me.desair.tus.server.util.TusServletResponse;
-/** A HEAD request is used to determine the offset at which the upload should be continued.
- *
- * The Server MUST always include the Upload-Offset header in the response for a HEAD request,
- * even if the offset is 0, or the upload is already considered completed. If the size of the upload is known,
- * the Server MUST include the Upload-Length header in the response.
- *
- * The Server MUST prevent the client and/or proxies from caching the response by adding
- * the Cache-Control: no-store header to the response.
+/**
+ * A HEAD request is used to determine the offset at which the upload should be continued.
+ *
+ * The Server MUST always include the Upload-Offset header in the response for a HEAD request,
+ * even if the offset is 0, or the upload is already considered completed. If the size of the upload
+ * is known, the Server MUST include the Upload-Length header in the response.
+ *
+ *
The Server MUST prevent the client and/or proxies from caching the response by adding the
+ * Cache-Control: no-store header to the response.
*/
public class CoreHeadRequestHandler extends AbstractRequestHandler {
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.HEAD.equals(method);
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.HEAD.equals(method);
+ }
+
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException {
+
+ UploadInfo uploadInfo =
+ uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
+
+ if (!UploadType.CONCATENATED.equals(uploadInfo.getUploadType())) {
+
+ if (uploadInfo.hasLength()) {
+ servletResponse.setHeader(
+ HttpHeader.UPLOAD_LENGTH, Objects.toString(uploadInfo.getLength()));
+ }
+ servletResponse.setHeader(HttpHeader.UPLOAD_OFFSET, Objects.toString(uploadInfo.getOffset()));
}
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException {
-
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
+ servletResponse.setHeader(HttpHeader.CACHE_CONTROL, "no-store");
- if (!UploadType.CONCATENATED.equals(uploadInfo.getUploadType())) {
-
- if (uploadInfo.hasLength()) {
- servletResponse.setHeader(HttpHeader.UPLOAD_LENGTH, Objects.toString(uploadInfo.getLength()));
- }
- servletResponse.setHeader(HttpHeader.UPLOAD_OFFSET, Objects.toString(uploadInfo.getOffset()));
- }
-
- servletResponse.setHeader(HttpHeader.CACHE_CONTROL, "no-store");
-
- servletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
- }
+ servletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/CoreOptionsRequestHandler.java b/src/main/java/me/desair/tus/server/core/CoreOptionsRequestHandler.java
index 150b12e..d31069f 100644
--- a/src/main/java/me/desair/tus/server/core/CoreOptionsRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/core/CoreOptionsRequestHandler.java
@@ -1,8 +1,7 @@
package me.desair.tus.server.core;
-import java.util.Objects;
import jakarta.servlet.http.HttpServletResponse;
-
+import java.util.Objects;
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.TusFileUploadService;
@@ -12,29 +11,32 @@
import me.desair.tus.server.util.TusServletResponse;
/**
- * An OPTIONS request MAY be used to gather information about the Server’s current configuration. A successful
- * response indicated by the 204 No Content or 200 OK status MUST contain the Tus-Version header. It MAY include
- * the Tus-Extension and Tus-Max-Size headers.
+ * An OPTIONS request MAY be used to gather information about the Server’s current configuration. A
+ * successful response indicated by the 204 No Content or 200 OK status MUST contain the Tus-Version
+ * header. It MAY include the Tus-Extension and Tus-Max-Size headers.
*/
public class CoreOptionsRequestHandler extends AbstractRequestHandler {
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.OPTIONS.equals(method);
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.OPTIONS.equals(method);
+ }
+
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey) {
+
+ if (uploadStorageService.getMaxUploadSize() > 0) {
+ servletResponse.setHeader(
+ HttpHeader.TUS_MAX_SIZE, Objects.toString(uploadStorageService.getMaxUploadSize()));
}
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) {
+ servletResponse.setHeader(HttpHeader.TUS_VERSION, TusFileUploadService.TUS_API_VERSION);
- if (uploadStorageService.getMaxUploadSize() > 0) {
- servletResponse.setHeader(HttpHeader.TUS_MAX_SIZE,
- Objects.toString(uploadStorageService.getMaxUploadSize()));
- }
-
- servletResponse.setHeader(HttpHeader.TUS_VERSION, TusFileUploadService.TUS_API_VERSION);
-
- servletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
- }
+ servletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/CorePatchRequestHandler.java b/src/main/java/me/desair/tus/server/core/CorePatchRequestHandler.java
index 882dc13..85894a7 100644
--- a/src/main/java/me/desair/tus/server/core/CorePatchRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/core/CorePatchRequestHandler.java
@@ -1,9 +1,8 @@
package me.desair.tus.server.core;
+import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
-import jakarta.servlet.http.HttpServletResponse;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.TusException;
@@ -17,52 +16,63 @@
import org.slf4j.LoggerFactory;
/**
- * The Server SHOULD accept PATCH requests against any upload URL and apply the bytes contained in the message at
- * the given offset specified by the Upload-Offset header.
- *
- * The Server MUST acknowledge successful PATCH requests with the 204 No Content status. It MUST include the
- * Upload-Offset header containing the new offset. The new offset MUST be the sum of the offset before the PATCH
- * request and the number of bytes received and processed or stored during the current PATCH request.
+ * The Server SHOULD accept PATCH requests against any upload URL and apply the bytes contained in
+ * the message at the given offset specified by the Upload-Offset header.
+ *
+ * The Server MUST acknowledge successful PATCH requests with the 204 No Content status. It MUST
+ * include the Upload-Offset header containing the new offset. The new offset MUST be the sum of the
+ * offset before the PATCH request and the number of bytes received and processed or stored during
+ * the current PATCH request.
*/
public class CorePatchRequestHandler extends AbstractRequestHandler {
- private static final Logger log = LoggerFactory.getLogger(CorePatchRequestHandler.class);
+ private static final Logger log = LoggerFactory.getLogger(CorePatchRequestHandler.class);
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.PATCH.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.PATCH.equals(method);
+ }
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException, TusException {
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
- boolean found = true;
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
+ boolean found = true;
+ UploadInfo uploadInfo =
+ uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
- if (uploadInfo == null) {
- found = false;
- } else if (uploadInfo.isUploadInProgress()) {
- try {
- uploadInfo = uploadStorageService.append(uploadInfo, servletRequest.getContentInputStream());
- } catch (UploadNotFoundException e) {
- found = false;
- }
- }
+ if (uploadInfo == null) {
+ found = false;
+ } else if (uploadInfo.isUploadInProgress()) {
+ try {
+ uploadInfo =
+ uploadStorageService.append(uploadInfo, servletRequest.getContentInputStream());
+ } catch (UploadNotFoundException e) {
+ found = false;
+ }
+ }
- if (found) {
- servletResponse.setHeader(HttpHeader.UPLOAD_OFFSET, Objects.toString(uploadInfo.getOffset()));
- servletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
+ if (found) {
+ servletResponse.setHeader(HttpHeader.UPLOAD_OFFSET, Objects.toString(uploadInfo.getOffset()));
+ servletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
- if (!uploadInfo.isUploadInProgress()) {
- log.info("Upload with ID {} at location {} finished successfully",
- uploadInfo.getId(), servletRequest.getRequestURI());
- }
- } else {
- log.error("The patch request handler could not find the upload for URL " + servletRequest.getRequestURI()
- + ". This means something is really wrong the request validators!");
- servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- }
+ if (!uploadInfo.isUploadInProgress()) {
+ log.info(
+ "Upload with ID {} at location {} finished successfully",
+ uploadInfo.getId(),
+ servletRequest.getRequestURI());
+ }
+ } else {
+ log.error(
+ "The patch request handler could not find the upload for URL "
+ + servletRequest.getRequestURI()
+ + ". This means something is really wrong the request validators!");
+ servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/CoreProtocol.java b/src/main/java/me/desair/tus/server/core/CoreProtocol.java
index 0a45c78..10ecfe0 100644
--- a/src/main/java/me/desair/tus/server/core/CoreProtocol.java
+++ b/src/main/java/me/desair/tus/server/core/CoreProtocol.java
@@ -3,7 +3,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
-
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestHandler;
import me.desair.tus.server.RequestValidator;
@@ -16,37 +15,37 @@
import me.desair.tus.server.util.AbstractTusExtension;
/**
- * The core protocol describes how to resume an interrupted upload.
- * It assumes that you already have a URL for the upload, usually created via the Creation extension.
- * All Clients and Servers MUST implement the core protocol.
+ * The core protocol describes how to resume an interrupted upload. It assumes that you already have
+ * a URL for the upload, usually created via the Creation extension. All Clients and Servers MUST
+ * implement the core protocol.
*/
public class CoreProtocol extends AbstractTusExtension {
- @Override
- public String getName() {
- return "core";
- }
+ @Override
+ public String getName() {
+ return "core";
+ }
- @Override
- public Collection getMinimalSupportedHttpMethods() {
- return Arrays.asList(HttpMethod.OPTIONS, HttpMethod.HEAD, HttpMethod.PATCH);
- }
+ @Override
+ public Collection getMinimalSupportedHttpMethods() {
+ return Arrays.asList(HttpMethod.OPTIONS, HttpMethod.HEAD, HttpMethod.PATCH);
+ }
- @Override
- protected void initValidators(List validators) {
- validators.add(new HttpMethodValidator());
- validators.add(new TusResumableValidator());
- validators.add(new IdExistsValidator());
- validators.add(new ContentTypeValidator());
- validators.add(new UploadOffsetValidator());
- validators.add(new ContentLengthValidator());
- }
+ @Override
+ protected void initValidators(List validators) {
+ validators.add(new HttpMethodValidator());
+ validators.add(new TusResumableValidator());
+ validators.add(new IdExistsValidator());
+ validators.add(new ContentTypeValidator());
+ validators.add(new UploadOffsetValidator());
+ validators.add(new ContentLengthValidator());
+ }
- @Override
- protected void initRequestHandlers(List requestHandlers) {
- requestHandlers.add(new CoreDefaultResponseHeadersHandler());
- requestHandlers.add(new CoreHeadRequestHandler());
- requestHandlers.add(new CorePatchRequestHandler());
- requestHandlers.add(new CoreOptionsRequestHandler());
- }
+ @Override
+ protected void initRequestHandlers(List requestHandlers) {
+ requestHandlers.add(new CoreDefaultResponseHeadersHandler());
+ requestHandlers.add(new CoreHeadRequestHandler());
+ requestHandlers.add(new CorePatchRequestHandler());
+ requestHandlers.add(new CoreOptionsRequestHandler());
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/validation/ContentLengthValidator.java b/src/main/java/me/desair/tus/server/core/validation/ContentLengthValidator.java
index c7c0f16..e787289 100644
--- a/src/main/java/me/desair/tus/server/core/validation/ContentLengthValidator.java
+++ b/src/main/java/me/desair/tus/server/core/validation/ContentLengthValidator.java
@@ -1,8 +1,7 @@
package me.desair.tus.server.core.validation;
-import java.io.IOException;
import jakarta.servlet.http.HttpServletRequest;
-
+import java.io.IOException;
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
@@ -13,34 +12,42 @@
import me.desair.tus.server.util.Utils;
/**
- * Validate that the given upload length in combination with the bytes we already received,
- * does not exceed the declared initial length on upload creation.
+ * Validate that the given upload length in combination with the bytes we already received, does not
+ * exceed the declared initial length on upload creation.
*/
public class ContentLengthValidator implements RequestValidator {
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws TusException, IOException {
-
- Long contentLength = Utils.getLongHeader(request, HttpHeader.CONTENT_LENGTH);
-
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(request.getRequestURI(), ownerKey);
-
- if (contentLength != null
- && uploadInfo != null
- && uploadInfo.hasLength()
- && (uploadInfo.getOffset() + contentLength > uploadInfo.getLength())) {
-
- throw new InvalidContentLengthException("The " + HttpHeader.CONTENT_LENGTH + " value " + contentLength
- + " in combination with the current offset " + uploadInfo.getOffset()
- + " exceeds the declared upload length " + uploadInfo.getLength());
- }
- }
-
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.PATCH.equals(method);
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws TusException, IOException {
+
+ Long contentLength = Utils.getLongHeader(request, HttpHeader.CONTENT_LENGTH);
+
+ UploadInfo uploadInfo = uploadStorageService.getUploadInfo(request.getRequestURI(), ownerKey);
+
+ if (contentLength != null
+ && uploadInfo != null
+ && uploadInfo.hasLength()
+ && (uploadInfo.getOffset() + contentLength > uploadInfo.getLength())) {
+
+ throw new InvalidContentLengthException(
+ "The "
+ + HttpHeader.CONTENT_LENGTH
+ + " value "
+ + contentLength
+ + " in combination with the current offset "
+ + uploadInfo.getOffset()
+ + " exceeds the declared upload length "
+ + uploadInfo.getLength());
}
+ }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.PATCH.equals(method);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/validation/ContentTypeValidator.java b/src/main/java/me/desair/tus/server/core/validation/ContentTypeValidator.java
index b90cd66..939006e 100644
--- a/src/main/java/me/desair/tus/server/core/validation/ContentTypeValidator.java
+++ b/src/main/java/me/desair/tus/server/core/validation/ContentTypeValidator.java
@@ -1,7 +1,6 @@
package me.desair.tus.server.core.validation;
import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
@@ -10,27 +9,31 @@
import me.desair.tus.server.upload.UploadStorageService;
import me.desair.tus.server.util.Utils;
-/**
- * All PATCH requests MUST use Content-Type: application/offset+octet-stream.
- */
+/** All PATCH requests MUST use Content-Type: application/offset+octet-stream. */
public class ContentTypeValidator implements RequestValidator {
- static final String APPLICATION_OFFSET_OCTET_STREAM = "application/offset+octet-stream";
-
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey) throws TusException {
-
- String contentType = Utils.getHeader(request, HttpHeader.CONTENT_TYPE);
- if (!APPLICATION_OFFSET_OCTET_STREAM.equals(contentType)) {
- throw new InvalidContentTypeException("The " + HttpHeader.CONTENT_TYPE + " header must contain value "
- + APPLICATION_OFFSET_OCTET_STREAM);
- }
- }
-
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.PATCH.equals(method);
+ static final String APPLICATION_OFFSET_OCTET_STREAM = "application/offset+octet-stream";
+
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws TusException {
+
+ String contentType = Utils.getHeader(request, HttpHeader.CONTENT_TYPE);
+ if (!APPLICATION_OFFSET_OCTET_STREAM.equals(contentType)) {
+ throw new InvalidContentTypeException(
+ "The "
+ + HttpHeader.CONTENT_TYPE
+ + " header must contain value "
+ + APPLICATION_OFFSET_OCTET_STREAM);
}
+ }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.PATCH.equals(method);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/validation/HttpMethodValidator.java b/src/main/java/me/desair/tus/server/core/validation/HttpMethodValidator.java
index 7238893..e12d7f5 100644
--- a/src/main/java/me/desair/tus/server/core/validation/HttpMethodValidator.java
+++ b/src/main/java/me/desair/tus/server/core/validation/HttpMethodValidator.java
@@ -1,30 +1,31 @@
package me.desair.tus.server.core.validation;
import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
import me.desair.tus.server.exception.TusException;
import me.desair.tus.server.exception.UnsupportedMethodException;
import me.desair.tus.server.upload.UploadStorageService;
-/**
- * Class to validate if the current HTTP method is valid
- */
+/** Class to validate if the current HTTP method is valid */
public class HttpMethodValidator implements RequestValidator {
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey) throws TusException {
-
- if (method == null) {
- throw new UnsupportedMethodException("The HTTP method " + request.getMethod() + " is not supported");
- }
- }
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws TusException {
- @Override
- public boolean supports(HttpMethod method) {
- return true;
+ if (method == null) {
+ throw new UnsupportedMethodException(
+ "The HTTP method " + request.getMethod() + " is not supported");
}
+ }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return true;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/validation/IdExistsValidator.java b/src/main/java/me/desair/tus/server/core/validation/IdExistsValidator.java
index 7dfcb09..b5190e1 100644
--- a/src/main/java/me/desair/tus/server/core/validation/IdExistsValidator.java
+++ b/src/main/java/me/desair/tus/server/core/validation/IdExistsValidator.java
@@ -1,8 +1,7 @@
package me.desair.tus.server.core.validation;
-import java.io.IOException;
import jakarta.servlet.http.HttpServletRequest;
-
+import java.io.IOException;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
import me.desair.tus.server.exception.TusException;
@@ -10,30 +9,35 @@
import me.desair.tus.server.upload.UploadStorageService;
/**
- * If the resource is not found, the Server SHOULD return either the
- * 404 Not Found, 410 Gone or 403 Forbidden status without the Upload-Offset header.
+ * If the resource is not found, the Server SHOULD return either the 404 Not Found, 410 Gone or 403
+ * Forbidden status without the Upload-Offset header.
*/
public class IdExistsValidator implements RequestValidator {
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws TusException, IOException {
-
- if (uploadStorageService.getUploadInfo(request.getRequestURI(), ownerKey) == null) {
- throw new UploadNotFoundException("The upload for path " + request.getRequestURI()
- + " and owner " + ownerKey + " was not found.");
- }
- }
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws TusException, IOException {
- @Override
- public boolean supports(HttpMethod method) {
- return method != null && (
- HttpMethod.HEAD.equals(method)
- || HttpMethod.PATCH.equals(method)
- || HttpMethod.DELETE.equals(method)
- || HttpMethod.GET.equals(method)
- );
+ if (uploadStorageService.getUploadInfo(request.getRequestURI(), ownerKey) == null) {
+ throw new UploadNotFoundException(
+ "The upload for path "
+ + request.getRequestURI()
+ + " and owner "
+ + ownerKey
+ + " was not found.");
}
+ }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return method != null
+ && (HttpMethod.HEAD.equals(method)
+ || HttpMethod.PATCH.equals(method)
+ || HttpMethod.DELETE.equals(method)
+ || HttpMethod.GET.equals(method));
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/validation/TusResumableValidator.java b/src/main/java/me/desair/tus/server/core/validation/TusResumableValidator.java
index 095b98d..b818d82 100644
--- a/src/main/java/me/desair/tus/server/core/validation/TusResumableValidator.java
+++ b/src/main/java/me/desair/tus/server/core/validation/TusResumableValidator.java
@@ -1,7 +1,6 @@
package me.desair.tus.server.core.validation;
import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
@@ -12,31 +11,36 @@
import me.desair.tus.server.util.Utils;
import org.apache.commons.lang3.StringUtils;
-/** Class that will validate if the tus version in the request corresponds to our implementation version
- *
- * The Tus-Resumable header MUST be included in every request and response except for OPTIONS requests.
- * The value MUST be the version of the protocol used by the Client or the Server.
- * If the the version specified by the Client is not supported by the Server, it MUST respond with the
- * 412 Precondition Failed status and MUST include the Tus-Version header into the response.
- * In addition, the Server MUST NOT process the request.
- *
- * (https://tus.io/protocols/resumable-upload.html#tus-resumable)
+/**
+ * Class that will validate if the tus version in the request corresponds to our implementation
+ * version
+ *
+ * The Tus-Resumable header MUST be included in every request and response except for OPTIONS
+ * requests. The value MUST be the version of the protocol used by the Client or the Server. If the
+ * the version specified by the Client is not supported by the Server, it MUST respond with the 412
+ * Precondition Failed status and MUST include the Tus-Version header into the response. In
+ * addition, the Server MUST NOT process the request.
+ *
+ *
(https://tus.io/protocols/resumable-upload.html#tus-resumable)
*/
public class TusResumableValidator implements RequestValidator {
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws TusException {
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws TusException {
- String requestVersion = Utils.getHeader(request, HttpHeader.TUS_RESUMABLE);
- if (!StringUtils.equals(requestVersion, TusFileUploadService.TUS_API_VERSION)) {
- throw new InvalidTusResumableException("This server does not support tus protocol version "
- + requestVersion);
- }
+ String requestVersion = Utils.getHeader(request, HttpHeader.TUS_RESUMABLE);
+ if (!StringUtils.equals(requestVersion, TusFileUploadService.TUS_API_VERSION)) {
+ throw new InvalidTusResumableException(
+ "This server does not support tus protocol version " + requestVersion);
}
+ }
- @Override
- public boolean supports(HttpMethod method) {
- return !HttpMethod.OPTIONS.equals(method) && !HttpMethod.GET.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return !HttpMethod.OPTIONS.equals(method) && !HttpMethod.GET.equals(method);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/core/validation/UploadOffsetValidator.java b/src/main/java/me/desair/tus/server/core/validation/UploadOffsetValidator.java
index 195ac30..61ae3e9 100644
--- a/src/main/java/me/desair/tus/server/core/validation/UploadOffsetValidator.java
+++ b/src/main/java/me/desair/tus/server/core/validation/UploadOffsetValidator.java
@@ -1,9 +1,8 @@
package me.desair.tus.server.core.validation;
+import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Objects;
-import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
@@ -15,34 +14,38 @@
import org.apache.commons.lang3.StringUtils;
/**
- * The Upload-Offset header’s value MUST be equal to the current offset of the resource.
- * If the offsets do not match, the Server MUST respond with the
- * 409 Conflict status without modifying the upload resource.
+ * The Upload-Offset header’s value MUST be equal to the current offset of the resource. If the
+ * offsets do not match, the Server MUST respond with the 409 Conflict status without modifying the
+ * upload resource.
*/
public class UploadOffsetValidator implements RequestValidator {
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws IOException, TusException {
-
- String uploadOffset = Utils.getHeader(request, HttpHeader.UPLOAD_OFFSET);
-
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(request.getRequestURI(), ownerKey);
-
- if (uploadInfo != null) {
- String expectedOffset = Objects.toString(uploadInfo.getOffset());
- if (!StringUtils.equals(expectedOffset, uploadOffset)) {
- throw new UploadOffsetMismatchException("The Upload-Offset was "
- + StringUtils.trimToNull(uploadOffset) + " but expected " + expectedOffset);
- }
- }
-
- }
-
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.PATCH.equals(method);
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
+
+ String uploadOffset = Utils.getHeader(request, HttpHeader.UPLOAD_OFFSET);
+
+ UploadInfo uploadInfo = uploadStorageService.getUploadInfo(request.getRequestURI(), ownerKey);
+
+ if (uploadInfo != null) {
+ String expectedOffset = Objects.toString(uploadInfo.getOffset());
+ if (!StringUtils.equals(expectedOffset, uploadOffset)) {
+ throw new UploadOffsetMismatchException(
+ "The Upload-Offset was "
+ + StringUtils.trimToNull(uploadOffset)
+ + " but expected "
+ + expectedOffset);
+ }
}
+ }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.PATCH.equals(method);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/creation/CreationExtension.java b/src/main/java/me/desair/tus/server/creation/CreationExtension.java
index 204b473..770b132 100644
--- a/src/main/java/me/desair/tus/server/creation/CreationExtension.java
+++ b/src/main/java/me/desair/tus/server/creation/CreationExtension.java
@@ -3,7 +3,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
-
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestHandler;
import me.desair.tus.server.RequestValidator;
@@ -14,33 +13,34 @@
import me.desair.tus.server.util.AbstractTusExtension;
/**
- * The Client and the Server SHOULD implement the upload creation extension. If the Server supports this extension.
+ * The Client and the Server SHOULD implement the upload creation extension. If the Server supports
+ * this extension.
*/
public class CreationExtension extends AbstractTusExtension {
- @Override
- public String getName() {
- return "creation";
- }
+ @Override
+ public String getName() {
+ return "creation";
+ }
- @Override
- public Collection getMinimalSupportedHttpMethods() {
- return Arrays.asList(HttpMethod.OPTIONS, HttpMethod.HEAD, HttpMethod.PATCH, HttpMethod.POST);
- }
+ @Override
+ public Collection getMinimalSupportedHttpMethods() {
+ return Arrays.asList(HttpMethod.OPTIONS, HttpMethod.HEAD, HttpMethod.PATCH, HttpMethod.POST);
+ }
- @Override
- protected void initValidators(List requestValidators) {
- requestValidators.add(new PostURIValidator());
- requestValidators.add(new PostEmptyRequestValidator());
- requestValidators.add(new UploadDeferLengthValidator());
- requestValidators.add(new UploadLengthValidator());
- }
+ @Override
+ protected void initValidators(List requestValidators) {
+ requestValidators.add(new PostURIValidator());
+ requestValidators.add(new PostEmptyRequestValidator());
+ requestValidators.add(new UploadDeferLengthValidator());
+ requestValidators.add(new UploadLengthValidator());
+ }
- @Override
- protected void initRequestHandlers(List requestHandlers) {
- requestHandlers.add(new CreationHeadRequestHandler());
- requestHandlers.add(new CreationPatchRequestHandler());
- requestHandlers.add(new CreationPostRequestHandler());
- requestHandlers.add(new CreationOptionsRequestHandler());
- }
+ @Override
+ protected void initRequestHandlers(List requestHandlers) {
+ requestHandlers.add(new CreationHeadRequestHandler());
+ requestHandlers.add(new CreationPatchRequestHandler());
+ requestHandlers.add(new CreationPostRequestHandler());
+ requestHandlers.add(new CreationOptionsRequestHandler());
+ }
}
diff --git a/src/main/java/me/desair/tus/server/creation/CreationHeadRequestHandler.java b/src/main/java/me/desair/tus/server/creation/CreationHeadRequestHandler.java
index c3417cb..1f5a375 100644
--- a/src/main/java/me/desair/tus/server/creation/CreationHeadRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/creation/CreationHeadRequestHandler.java
@@ -1,7 +1,6 @@
package me.desair.tus.server.creation;
import java.io.IOException;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.upload.UploadInfo;
@@ -11,34 +10,40 @@
import me.desair.tus.server.util.TusServletRequest;
import me.desair.tus.server.util.TusServletResponse;
-/** A HEAD request can be used to retrieve the metadata that was supplied at creation.
- *
- * If an upload contains additional metadata, responses to HEAD requests MUST include the Upload-Metadata
- * header and its value as specified by the Client during the creation.
- *
- * As long as the length of the upload is not known, the Server MUST set Upload-Defer-Length: 1 in
- * all responses to HEAD requests.
+/**
+ * A HEAD request can be used to retrieve the metadata that was supplied at creation.
+ *
+ * If an upload contains additional metadata, responses to HEAD requests MUST include the
+ * Upload-Metadata header and its value as specified by the Client during the creation.
+ *
+ *
As long as the length of the upload is not known, the Server MUST set Upload-Defer-Length: 1
+ * in all responses to HEAD requests.
*/
public class CreationHeadRequestHandler extends AbstractRequestHandler {
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.HEAD.equals(method);
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.HEAD.equals(method);
+ }
+
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException {
+
+ UploadInfo uploadInfo =
+ uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
+
+ if (uploadInfo.hasMetadata()) {
+ servletResponse.setHeader(HttpHeader.UPLOAD_METADATA, uploadInfo.getEncodedMetadata());
}
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException {
-
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
-
- if (uploadInfo.hasMetadata()) {
- servletResponse.setHeader(HttpHeader.UPLOAD_METADATA, uploadInfo.getEncodedMetadata());
- }
-
- if (!uploadInfo.hasLength() && !UploadType.CONCATENATED.equals(uploadInfo.getUploadType())) {
- servletResponse.setHeader(HttpHeader.UPLOAD_DEFER_LENGTH, "1");
- }
+ if (!uploadInfo.hasLength() && !UploadType.CONCATENATED.equals(uploadInfo.getUploadType())) {
+ servletResponse.setHeader(HttpHeader.UPLOAD_DEFER_LENGTH, "1");
}
+ }
}
diff --git a/src/main/java/me/desair/tus/server/creation/CreationOptionsRequestHandler.java b/src/main/java/me/desair/tus/server/creation/CreationOptionsRequestHandler.java
index b6f53bd..30657a2 100644
--- a/src/main/java/me/desair/tus/server/creation/CreationOptionsRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/creation/CreationOptionsRequestHandler.java
@@ -3,17 +3,17 @@
import me.desair.tus.server.util.AbstractExtensionRequestHandler;
/**
- * The Client and the Server SHOULD implement the upload creation extension.
- * If the Server supports this extension, it MUST add creation to the Tus-Extension header.
- *
- * If the Server supports deferring length, it MUST add creation-defer-length to the Tus-Extension header.
+ * The Client and the Server SHOULD implement the upload creation extension. If the Server supports
+ * this extension, it MUST add creation to the Tus-Extension header.
+ *
+ * If the Server supports deferring length, it MUST add creation-defer-length to the
+ * Tus-Extension header.
*/
public class CreationOptionsRequestHandler extends AbstractExtensionRequestHandler {
- @Override
- protected void appendExtensions(StringBuilder extensionBuilder) {
- addExtension(extensionBuilder, "creation");
- addExtension(extensionBuilder, "creation-defer-length");
- }
-
+ @Override
+ protected void appendExtensions(StringBuilder extensionBuilder) {
+ addExtension(extensionBuilder, "creation");
+ addExtension(extensionBuilder, "creation-defer-length");
+ }
}
diff --git a/src/main/java/me/desair/tus/server/creation/CreationPatchRequestHandler.java b/src/main/java/me/desair/tus/server/creation/CreationPatchRequestHandler.java
index fd07b9c..c6baf32 100644
--- a/src/main/java/me/desair/tus/server/creation/CreationPatchRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/creation/CreationPatchRequestHandler.java
@@ -1,8 +1,7 @@
package me.desair.tus.server.creation;
-import java.io.IOException;
import jakarta.servlet.http.HttpServletResponse;
-
+import java.io.IOException;
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.UploadNotFoundException;
@@ -16,38 +15,45 @@
import org.slf4j.LoggerFactory;
/**
- * Upload-Defer-Length: 1 if upload size is not known at the time. Once it is known the Client MUST set
- * the Upload-Length header in the next PATCH request. Once set the length MUST NOT be changed.
+ * Upload-Defer-Length: 1 if upload size is not known at the time. Once it is known the Client MUST
+ * set the Upload-Length header in the next PATCH request. Once set the length MUST NOT be changed.
*/
public class CreationPatchRequestHandler extends AbstractRequestHandler {
- private static final Logger log = LoggerFactory.getLogger(CreationPatchRequestHandler.class);
-
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.PATCH.equals(method);
- }
-
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException {
-
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
-
- if (uploadInfo != null && !uploadInfo.hasLength()) {
- Long uploadLength = Utils.getLongHeader(servletRequest, HttpHeader.UPLOAD_LENGTH);
- if (uploadLength != null) {
- uploadInfo.setLength(uploadLength);
- try {
- uploadStorageService.update(uploadInfo);
- } catch (UploadNotFoundException e) {
- log.error("The patch request handler could not find the upload for URL "
- + servletRequest.getRequestURI()
- + ". This means something is really wrong the request validators!", e);
- servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- }
- }
+ private static final Logger log = LoggerFactory.getLogger(CreationPatchRequestHandler.class);
+
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.PATCH.equals(method);
+ }
+
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException {
+
+ UploadInfo uploadInfo =
+ uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
+
+ if (uploadInfo != null && !uploadInfo.hasLength()) {
+ Long uploadLength = Utils.getLongHeader(servletRequest, HttpHeader.UPLOAD_LENGTH);
+ if (uploadLength != null) {
+ uploadInfo.setLength(uploadLength);
+ try {
+ uploadStorageService.update(uploadInfo);
+ } catch (UploadNotFoundException e) {
+ log.error(
+ "The patch request handler could not find the upload for URL "
+ + servletRequest.getRequestURI()
+ + ". This means something is really wrong the request validators!",
+ e);
+ servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
+ }
}
+ }
}
diff --git a/src/main/java/me/desair/tus/server/creation/CreationPostRequestHandler.java b/src/main/java/me/desair/tus/server/creation/CreationPostRequestHandler.java
index 1bbf9ea..e115bf8 100644
--- a/src/main/java/me/desair/tus/server/creation/CreationPostRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/creation/CreationPostRequestHandler.java
@@ -1,9 +1,8 @@
package me.desair.tus.server.creation;
-import java.io.IOException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
-
+import java.io.IOException;
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.upload.UploadInfo;
@@ -17,52 +16,64 @@
import org.slf4j.LoggerFactory;
/**
- * The Server MUST acknowledge a successful upload creation with the 201 Created status.
- * The Server MUST set the Location header to the URL of the created resource. This URL MAY be absolute or relative.
+ * The Server MUST acknowledge a successful upload creation with the 201 Created status. The Server
+ * MUST set the Location header to the URL of the created resource. This URL MAY be absolute or
+ * relative.
*/
public class CreationPostRequestHandler extends AbstractRequestHandler {
- private static final Logger log = LoggerFactory.getLogger(CreationPostRequestHandler.class);
-
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.POST.equals(method);
- }
+ private static final Logger log = LoggerFactory.getLogger(CreationPostRequestHandler.class);
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException {
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.POST.equals(method);
+ }
- UploadInfo info = buildUploadInfo(servletRequest);
- info = uploadStorageService.create(info, ownerKey);
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException {
- //We've already validated that the current request URL matches our upload URL so we can safely use it.
- String uploadURI = servletRequest.getRequestURI();
+ UploadInfo info = buildUploadInfo(servletRequest);
+ info = uploadStorageService.create(info, ownerKey);
- //It's important to return relative UPLOAD URLs in the Location header in order to support HTTPS proxies
- //that sit in front of the web app
- String url = uploadURI + (StringUtils.endsWith(uploadURI, "/") ? "" : "/") + info.getId();
- servletResponse.setHeader(HttpHeader.LOCATION, url);
- servletResponse.setStatus(HttpServletResponse.SC_CREATED);
+ // We've already validated that the current request URL matches our upload URL so we can
+ // safely
+ // use it.
+ String uploadURI = servletRequest.getRequestURI();
- log.info("Created upload with ID {} at {} for ip address {} with location {}",
- info.getId(), info.getCreationTimestamp(), info.getCreatorIpAddresses(), url);
- }
+ // It's important to return relative UPLOAD URLs in the Location header in order to support
+ // HTTPS proxies
+ // that sit in front of the web app
+ String url = uploadURI + (StringUtils.endsWith(uploadURI, "/") ? "" : "/") + info.getId();
+ servletResponse.setHeader(HttpHeader.LOCATION, url);
+ servletResponse.setStatus(HttpServletResponse.SC_CREATED);
- private UploadInfo buildUploadInfo(HttpServletRequest servletRequest) {
- UploadInfo info = new UploadInfo(servletRequest);
+ log.info(
+ "Created upload with ID {} at {} for ip address {} with location {}",
+ info.getId(),
+ info.getCreationTimestamp(),
+ info.getCreatorIpAddresses(),
+ url);
+ }
- Long length = Utils.getLongHeader(servletRequest, HttpHeader.UPLOAD_LENGTH);
- if (length != null) {
- info.setLength(length);
- }
+ private UploadInfo buildUploadInfo(HttpServletRequest servletRequest) {
+ UploadInfo info = new UploadInfo(servletRequest);
- String metadata = Utils.getHeader(servletRequest, HttpHeader.UPLOAD_METADATA);
- if (StringUtils.isNotBlank(metadata)) {
- info.setEncodedMetadata(metadata);
- }
+ Long length = Utils.getLongHeader(servletRequest, HttpHeader.UPLOAD_LENGTH);
+ if (length != null) {
+ info.setLength(length);
+ }
- return info;
+ String metadata = Utils.getHeader(servletRequest, HttpHeader.UPLOAD_METADATA);
+ if (StringUtils.isNotBlank(metadata)) {
+ info.setEncodedMetadata(metadata);
}
+
+ return info;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/creation/validation/PostEmptyRequestValidator.java b/src/main/java/me/desair/tus/server/creation/validation/PostEmptyRequestValidator.java
index acff53b..12c860a 100644
--- a/src/main/java/me/desair/tus/server/creation/validation/PostEmptyRequestValidator.java
+++ b/src/main/java/me/desair/tus/server/creation/validation/PostEmptyRequestValidator.java
@@ -1,7 +1,6 @@
package me.desair.tus.server.creation.validation;
import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
@@ -10,25 +9,26 @@
import me.desair.tus.server.upload.UploadStorageService;
import me.desair.tus.server.util.Utils;
-/**
- * An empty POST request is used to create a new upload resource.
- */
+/** An empty POST request is used to create a new upload resource. */
public class PostEmptyRequestValidator implements RequestValidator {
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws TusException {
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws TusException {
- Long contentLength = Utils.getLongHeader(request, HttpHeader.CONTENT_LENGTH);
- if (contentLength != null && contentLength > 0) {
- throw new InvalidContentLengthException("A POST request should have a Content-Length header with value "
- + "0 and no content");
- }
+ Long contentLength = Utils.getLongHeader(request, HttpHeader.CONTENT_LENGTH);
+ if (contentLength != null && contentLength > 0) {
+ throw new InvalidContentLengthException(
+ "A POST request should have a Content-Length header with value " + "0 and no content");
}
+ }
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.POST.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.POST.equals(method);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/creation/validation/PostURIValidator.java b/src/main/java/me/desair/tus/server/creation/validation/PostURIValidator.java
index b3f522f..3b5ed1b 100644
--- a/src/main/java/me/desair/tus/server/creation/validation/PostURIValidator.java
+++ b/src/main/java/me/desair/tus/server/creation/validation/PostURIValidator.java
@@ -1,9 +1,8 @@
package me.desair.tus.server.creation.validation;
+import jakarta.servlet.http.HttpServletRequest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
import me.desair.tus.server.exception.PostOnInvalidRequestURIException;
@@ -11,36 +10,40 @@
import me.desair.tus.server.upload.UploadStorageService;
/**
- * The Client MUST send a POST request against a known upload creation URL to request a new upload resource.
+ * The Client MUST send a POST request against a known upload creation URL to request a new upload
+ * resource.
*/
public class PostURIValidator implements RequestValidator {
- private Pattern uploadUriPattern = null;
+ private Pattern uploadUriPattern = null;
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws TusException {
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws TusException {
- Matcher uploadUriMatcher = getUploadUriPattern(uploadStorageService).matcher(request.getRequestURI());
+ Matcher uploadUriMatcher =
+ getUploadUriPattern(uploadStorageService).matcher(request.getRequestURI());
- if (!uploadUriMatcher.matches()) {
- throw new PostOnInvalidRequestURIException("POST requests have to be sent to '"
- + uploadStorageService.getUploadURI() + "'. ");
- }
+ if (!uploadUriMatcher.matches()) {
+ throw new PostOnInvalidRequestURIException(
+ "POST requests have to be sent to '" + uploadStorageService.getUploadURI() + "'. ");
}
+ }
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.POST.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.POST.equals(method);
+ }
- private Pattern getUploadUriPattern(UploadStorageService uploadStorageService) {
- if (uploadUriPattern == null) {
- //A POST request should match the full URI
- uploadUriPattern = Pattern.compile("^" + uploadStorageService.getUploadURI() + "$");
- }
- return uploadUriPattern;
+ private Pattern getUploadUriPattern(UploadStorageService uploadStorageService) {
+ if (uploadUriPattern == null) {
+ // A POST request should match the full URI
+ uploadUriPattern = Pattern.compile("^" + uploadStorageService.getUploadURI() + "$");
}
-
+ return uploadUriPattern;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/creation/validation/UploadDeferLengthValidator.java b/src/main/java/me/desair/tus/server/creation/validation/UploadDeferLengthValidator.java
index 1a3f406..88cc7d4 100644
--- a/src/main/java/me/desair/tus/server/creation/validation/UploadDeferLengthValidator.java
+++ b/src/main/java/me/desair/tus/server/creation/validation/UploadDeferLengthValidator.java
@@ -1,7 +1,6 @@
package me.desair.tus.server.creation.validation;
import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
@@ -12,45 +11,54 @@
import org.apache.commons.lang3.StringUtils;
/**
- * The request MUST include one of the following headers:
- * a) Upload-Length to indicate the size of an entire upload in bytes.
- * b) Upload-Defer-Length: 1 if upload size is not known at the time.
+ * The request MUST include one of the following headers: a) Upload-Length to indicate the size of
+ * an entire upload in bytes. b) Upload-Defer-Length: 1 if upload size is not known at the time.
*/
public class UploadDeferLengthValidator implements RequestValidator {
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws TusException {
-
- boolean uploadLength = false;
- boolean deferredLength = false;
- boolean concatenatedUpload = false;
-
- if (StringUtils.isNumeric(Utils.getHeader(request, HttpHeader.UPLOAD_LENGTH))) {
- uploadLength = true;
- }
-
- if (Utils.getHeader(request, HttpHeader.UPLOAD_DEFER_LENGTH).equals("1")) {
- deferredLength = true;
- }
-
- String uploadConcatValue = request.getHeader(HttpHeader.UPLOAD_CONCAT);
- if (StringUtils.startsWithIgnoreCase(uploadConcatValue, "final")) {
- concatenatedUpload = true;
- }
-
- if (!concatenatedUpload && !uploadLength && !deferredLength) {
- throw new InvalidUploadLengthException("No valid value was found in headers " + HttpHeader.UPLOAD_LENGTH
- + " and " + HttpHeader.UPLOAD_DEFER_LENGTH);
- } else if (uploadLength && deferredLength) {
- throw new InvalidUploadLengthException("A POST request cannot contain both " + HttpHeader.UPLOAD_LENGTH
- + " and " + HttpHeader.UPLOAD_DEFER_LENGTH + " headers.");
- }
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws TusException {
+
+ boolean uploadLength = false;
+ boolean deferredLength = false;
+ boolean concatenatedUpload = false;
+
+ if (StringUtils.isNumeric(Utils.getHeader(request, HttpHeader.UPLOAD_LENGTH))) {
+ uploadLength = true;
+ }
+
+ if (Utils.getHeader(request, HttpHeader.UPLOAD_DEFER_LENGTH).equals("1")) {
+ deferredLength = true;
+ }
+
+ String uploadConcatValue = request.getHeader(HttpHeader.UPLOAD_CONCAT);
+ if (StringUtils.startsWithIgnoreCase(uploadConcatValue, "final")) {
+ concatenatedUpload = true;
}
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.POST.equals(method);
+ if (!concatenatedUpload && !uploadLength && !deferredLength) {
+ throw new InvalidUploadLengthException(
+ "No valid value was found in headers "
+ + HttpHeader.UPLOAD_LENGTH
+ + " and "
+ + HttpHeader.UPLOAD_DEFER_LENGTH);
+ } else if (uploadLength && deferredLength) {
+ throw new InvalidUploadLengthException(
+ "A POST request cannot contain both "
+ + HttpHeader.UPLOAD_LENGTH
+ + " and "
+ + HttpHeader.UPLOAD_DEFER_LENGTH
+ + " headers.");
}
+ }
+
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.POST.equals(method);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/creation/validation/UploadLengthValidator.java b/src/main/java/me/desair/tus/server/creation/validation/UploadLengthValidator.java
index 58882a6..3baf6fc 100644
--- a/src/main/java/me/desair/tus/server/creation/validation/UploadLengthValidator.java
+++ b/src/main/java/me/desair/tus/server/creation/validation/UploadLengthValidator.java
@@ -1,7 +1,6 @@
package me.desair.tus.server.creation.validation;
import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestValidator;
@@ -11,28 +10,31 @@
import me.desair.tus.server.util.Utils;
/**
- * If the length of the upload exceeds the maximum, which MAY be specified using the Tus-Max-Size header,
- * the Server MUST respond with the 413 Request Entity Too Large status.
+ * If the length of the upload exceeds the maximum, which MAY be specified using the Tus-Max-Size
+ * header, the Server MUST respond with the 413 Request Entity Too Large status.
*/
public class UploadLengthValidator implements RequestValidator {
- @Override
- public void validate(HttpMethod method, HttpServletRequest request,
- UploadStorageService uploadStorageService, String ownerKey)
- throws TusException {
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest request,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws TusException {
- Long uploadLength = Utils.getLongHeader(request, HttpHeader.UPLOAD_LENGTH);
- if (uploadLength != null
- && uploadStorageService.getMaxUploadSize() > 0
- && uploadLength > uploadStorageService.getMaxUploadSize()) {
+ Long uploadLength = Utils.getLongHeader(request, HttpHeader.UPLOAD_LENGTH);
+ if (uploadLength != null
+ && uploadStorageService.getMaxUploadSize() > 0
+ && uploadLength > uploadStorageService.getMaxUploadSize()) {
- throw new MaxUploadLengthExceededException("Upload requests can have a maximum size of "
- + uploadStorageService.getMaxUploadSize());
- }
+ throw new MaxUploadLengthExceededException(
+ "Upload requests can have a maximum size of " + uploadStorageService.getMaxUploadSize());
}
+ }
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.POST.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.POST.equals(method);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/download/DownloadExtension.java b/src/main/java/me/desair/tus/server/download/DownloadExtension.java
index c3c6eda..c6d6ceb 100644
--- a/src/main/java/me/desair/tus/server/download/DownloadExtension.java
+++ b/src/main/java/me/desair/tus/server/download/DownloadExtension.java
@@ -3,36 +3,35 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
-
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestHandler;
import me.desair.tus.server.RequestValidator;
import me.desair.tus.server.util.AbstractTusExtension;
/**
- * Some Tus clients also send GET request to retrieve the uploaded content. We consider this
- * as an unofficial extension.
+ * Some Tus clients also send GET request to retrieve the uploaded content. We consider this as an
+ * unofficial extension.
*/
public class DownloadExtension extends AbstractTusExtension {
- @Override
- public String getName() {
- return "download";
- }
+ @Override
+ public String getName() {
+ return "download";
+ }
- @Override
- public Collection getMinimalSupportedHttpMethods() {
- return Arrays.asList(HttpMethod.OPTIONS, HttpMethod.GET);
- }
+ @Override
+ public Collection getMinimalSupportedHttpMethods() {
+ return Arrays.asList(HttpMethod.OPTIONS, HttpMethod.GET);
+ }
- @Override
- protected void initValidators(List requestValidators) {
- //All validation is all read done by the Core protocol
- }
+ @Override
+ protected void initValidators(List requestValidators) {
+ // All validation is all read done by the Core protocol
+ }
- @Override
- protected void initRequestHandlers(List requestHandlers) {
- requestHandlers.add(new DownloadGetRequestHandler());
- requestHandlers.add(new DownloadOptionsRequestHandler());
- }
+ @Override
+ protected void initRequestHandlers(List requestHandlers) {
+ requestHandlers.add(new DownloadGetRequestHandler());
+ requestHandlers.add(new DownloadOptionsRequestHandler());
+ }
}
diff --git a/src/main/java/me/desair/tus/server/download/DownloadGetRequestHandler.java b/src/main/java/me/desair/tus/server/download/DownloadGetRequestHandler.java
index 82f5590..809a0e7 100644
--- a/src/main/java/me/desair/tus/server/download/DownloadGetRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/download/DownloadGetRequestHandler.java
@@ -1,11 +1,10 @@
package me.desair.tus.server.download;
+import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
-import jakarta.servlet.http.HttpServletResponse;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.TusException;
@@ -16,45 +15,54 @@
import me.desair.tus.server.util.TusServletRequest;
import me.desair.tus.server.util.TusServletResponse;
-/**
- * Send the uploaded bytes of finished uploads
- */
+/** Send the uploaded bytes of finished uploads */
public class DownloadGetRequestHandler extends AbstractRequestHandler {
- private static final String CONTENT_DISPOSITION_FORMAT = "attachment; filename=\"%s\"; filename*=UTF-8''%s";
+ private static final String CONTENT_DISPOSITION_FORMAT =
+ "attachment; filename=\"%s\"; filename*=UTF-8''%s";
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.GET.equals(method);
- }
-
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException, TusException {
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.GET.equals(method);
+ }
- UploadInfo info = uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
- if (info == null || info.isUploadInProgress()) {
- throw new UploadInProgressException("Upload " + servletRequest.getRequestURI() + " is still in progress "
- + "and cannot be downloaded yet");
- } else {
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
- servletResponse.setHeader(HttpHeader.CONTENT_LENGTH, Objects.toString(info.getLength()));
+ UploadInfo info = uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
+ if (info == null || info.isUploadInProgress()) {
+ throw new UploadInProgressException(
+ "Upload "
+ + servletRequest.getRequestURI()
+ + " is still in progress "
+ + "and cannot be downloaded yet");
+ } else {
- servletResponse.setHeader(HttpHeader.CONTENT_DISPOSITION,
- String.format(CONTENT_DISPOSITION_FORMAT, info.getFileName(),
- URLEncoder.encode(info.getFileName(),
- StandardCharsets.UTF_8.toString()).replace("+","%20")));
+ servletResponse.setHeader(HttpHeader.CONTENT_LENGTH, Objects.toString(info.getLength()));
- servletResponse.setHeader(HttpHeader.CONTENT_TYPE, info.getFileMimeType());
+ servletResponse.setHeader(
+ HttpHeader.CONTENT_DISPOSITION,
+ String.format(
+ CONTENT_DISPOSITION_FORMAT,
+ info.getFileName(),
+ URLEncoder.encode(info.getFileName(), StandardCharsets.UTF_8.toString())
+ .replace("+", "%20")));
- if (info.hasMetadata()) {
- servletResponse.setHeader(HttpHeader.UPLOAD_METADATA, info.getEncodedMetadata());
- }
+ servletResponse.setHeader(HttpHeader.CONTENT_TYPE, info.getFileMimeType());
- uploadStorageService.copyUploadTo(info, servletResponse.getOutputStream());
- }
+ if (info.hasMetadata()) {
+ servletResponse.setHeader(HttpHeader.UPLOAD_METADATA, info.getEncodedMetadata());
+ }
- servletResponse.setStatus(HttpServletResponse.SC_OK);
+ uploadStorageService.copyUploadTo(info, servletResponse.getOutputStream());
}
+
+ servletResponse.setStatus(HttpServletResponse.SC_OK);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/download/DownloadOptionsRequestHandler.java b/src/main/java/me/desair/tus/server/download/DownloadOptionsRequestHandler.java
index d810141..29a410f 100644
--- a/src/main/java/me/desair/tus/server/download/DownloadOptionsRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/download/DownloadOptionsRequestHandler.java
@@ -2,14 +2,11 @@
import me.desair.tus.server.util.AbstractExtensionRequestHandler;
-/**
- * Add our download extension the Tus-Extension header
- */
+/** Add our download extension the Tus-Extension header */
public class DownloadOptionsRequestHandler extends AbstractExtensionRequestHandler {
- @Override
- protected void appendExtensions(StringBuilder extensionBuilder) {
- addExtension(extensionBuilder, "download");
- }
-
+ @Override
+ protected void appendExtensions(StringBuilder extensionBuilder) {
+ addExtension(extensionBuilder, "download");
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/ChecksumAlgorithmNotSupportedException.java b/src/main/java/me/desair/tus/server/exception/ChecksumAlgorithmNotSupportedException.java
index 9e0890c..1bdd419 100644
--- a/src/main/java/me/desair/tus/server/exception/ChecksumAlgorithmNotSupportedException.java
+++ b/src/main/java/me/desair/tus/server/exception/ChecksumAlgorithmNotSupportedException.java
@@ -2,11 +2,9 @@
import jakarta.servlet.http.HttpServletResponse;
-/**
- * Exception thrown when the client sends a request for a checksum algorithm we do not support
- */
+/** Exception thrown when the client sends a request for a checksum algorithm we do not support */
public class ChecksumAlgorithmNotSupportedException extends TusException {
- public ChecksumAlgorithmNotSupportedException(String message) {
- super(HttpServletResponse.SC_BAD_REQUEST, message);
- }
+ public ChecksumAlgorithmNotSupportedException(String message) {
+ super(HttpServletResponse.SC_BAD_REQUEST, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/InvalidContentLengthException.java b/src/main/java/me/desair/tus/server/exception/InvalidContentLengthException.java
index 84d3469..1255108 100644
--- a/src/main/java/me/desair/tus/server/exception/InvalidContentLengthException.java
+++ b/src/main/java/me/desair/tus/server/exception/InvalidContentLengthException.java
@@ -3,7 +3,7 @@
import jakarta.servlet.http.HttpServletResponse;
public class InvalidContentLengthException extends TusException {
- public InvalidContentLengthException(String message) {
- super(HttpServletResponse.SC_BAD_REQUEST, message);
- }
+ public InvalidContentLengthException(String message) {
+ super(HttpServletResponse.SC_BAD_REQUEST, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/InvalidContentTypeException.java b/src/main/java/me/desair/tus/server/exception/InvalidContentTypeException.java
index de55671..378474b 100644
--- a/src/main/java/me/desair/tus/server/exception/InvalidContentTypeException.java
+++ b/src/main/java/me/desair/tus/server/exception/InvalidContentTypeException.java
@@ -2,11 +2,9 @@
import jakarta.servlet.http.HttpServletResponse;
-/**
- * Exception thrown when the request has an invalid content type.
- */
+/** Exception thrown when the request has an invalid content type. */
public class InvalidContentTypeException extends TusException {
- public InvalidContentTypeException(String message) {
- super(HttpServletResponse.SC_NOT_ACCEPTABLE, message);
- }
+ public InvalidContentTypeException(String message) {
+ super(HttpServletResponse.SC_NOT_ACCEPTABLE, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/InvalidPartialUploadIdException.java b/src/main/java/me/desair/tus/server/exception/InvalidPartialUploadIdException.java
index cb53027..3314a04 100644
--- a/src/main/java/me/desair/tus/server/exception/InvalidPartialUploadIdException.java
+++ b/src/main/java/me/desair/tus/server/exception/InvalidPartialUploadIdException.java
@@ -2,11 +2,9 @@
import jakarta.servlet.http.HttpServletResponse;
-/**
- * Exception thrown when the Upload-Concat header contains an ID which is not valid
- */
+/** Exception thrown when the Upload-Concat header contains an ID which is not valid */
public class InvalidPartialUploadIdException extends TusException {
- public InvalidPartialUploadIdException(String message) {
- super(HttpServletResponse.SC_PRECONDITION_FAILED, message);
- }
+ public InvalidPartialUploadIdException(String message) {
+ super(HttpServletResponse.SC_PRECONDITION_FAILED, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/InvalidTusResumableException.java b/src/main/java/me/desair/tus/server/exception/InvalidTusResumableException.java
index 94a5c04..53d1d44 100644
--- a/src/main/java/me/desair/tus/server/exception/InvalidTusResumableException.java
+++ b/src/main/java/me/desair/tus/server/exception/InvalidTusResumableException.java
@@ -2,19 +2,20 @@
import jakarta.servlet.http.HttpServletResponse;
-/** Exception thrown when receiving a request with a tus protocol version we do not support
- *
- * The Tus-Resumable header MUST be included in every request and response except for OPTIONS requests.
- * The value MUST be the version of the protocol used by the Client or the Server.
- * If the the version specified by the Client is not supported by the Server, it MUST respond with the
- * 412 Precondition Failed status and MUST include the Tus-Version header into the response.
- * In addition, the Server MUST NOT process the request.
- *
- * (https://tus.io/protocols/resumable-upload.html#tus-resumable)
+/**
+ * Exception thrown when receiving a request with a tus protocol version we do not support
+ *
+ * The Tus-Resumable header MUST be included in every request and response except for OPTIONS
+ * requests. The value MUST be the version of the protocol used by the Client or the Server. If the
+ * the version specified by the Client is not supported by the Server, it MUST respond with the 412
+ * Precondition Failed status and MUST include the Tus-Version header into the response. In
+ * addition, the Server MUST NOT process the request.
+ *
+ *
(https://tus.io/protocols/resumable-upload.html#tus-resumable)
*/
public class InvalidTusResumableException extends TusException {
- public InvalidTusResumableException(String message) {
- super(HttpServletResponse.SC_PRECONDITION_FAILED, message);
- }
+ public InvalidTusResumableException(String message) {
+ super(HttpServletResponse.SC_PRECONDITION_FAILED, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/InvalidUploadLengthException.java b/src/main/java/me/desair/tus/server/exception/InvalidUploadLengthException.java
index 46a9f30..22f04e2 100644
--- a/src/main/java/me/desair/tus/server/exception/InvalidUploadLengthException.java
+++ b/src/main/java/me/desair/tus/server/exception/InvalidUploadLengthException.java
@@ -2,12 +2,10 @@
import jakarta.servlet.http.HttpServletResponse;
-/**
- * Exception thrown when no valid Upload-Length or Upload-Defer-Length header is found
- */
+/** Exception thrown when no valid Upload-Length or Upload-Defer-Length header is found */
public class InvalidUploadLengthException extends TusException {
- public InvalidUploadLengthException(String message) {
- super(HttpServletResponse.SC_BAD_REQUEST, message);
- }
+ public InvalidUploadLengthException(String message) {
+ super(HttpServletResponse.SC_BAD_REQUEST, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/InvalidUploadOffsetException.java b/src/main/java/me/desair/tus/server/exception/InvalidUploadOffsetException.java
index 5bfc74b..7bd7294 100644
--- a/src/main/java/me/desair/tus/server/exception/InvalidUploadOffsetException.java
+++ b/src/main/java/me/desair/tus/server/exception/InvalidUploadOffsetException.java
@@ -3,7 +3,7 @@
import jakarta.servlet.http.HttpServletResponse;
public class InvalidUploadOffsetException extends TusException {
- public InvalidUploadOffsetException(String message) {
- super(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
- }
+ public InvalidUploadOffsetException(String message) {
+ super(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/MaxUploadLengthExceededException.java b/src/main/java/me/desair/tus/server/exception/MaxUploadLengthExceededException.java
index 15d8947..136f858 100644
--- a/src/main/java/me/desair/tus/server/exception/MaxUploadLengthExceededException.java
+++ b/src/main/java/me/desair/tus/server/exception/MaxUploadLengthExceededException.java
@@ -2,11 +2,9 @@
import jakarta.servlet.http.HttpServletResponse;
-/**
- * Exception thrown when the given upload length exceeds or internally defined maximum
- */
+/** Exception thrown when the given upload length exceeds or internally defined maximum */
public class MaxUploadLengthExceededException extends TusException {
- public MaxUploadLengthExceededException(String message) {
- super(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, message);
- }
+ public MaxUploadLengthExceededException(String message) {
+ super(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/PatchOnFinalUploadNotAllowedException.java b/src/main/java/me/desair/tus/server/exception/PatchOnFinalUploadNotAllowedException.java
index b693e76..e74ac05 100644
--- a/src/main/java/me/desair/tus/server/exception/PatchOnFinalUploadNotAllowedException.java
+++ b/src/main/java/me/desair/tus/server/exception/PatchOnFinalUploadNotAllowedException.java
@@ -2,12 +2,10 @@
import jakarta.servlet.http.HttpServletResponse;
-/**
- * The Server MUST respond with the 403 Forbidden status to PATCH requests against a upload URL
- */
+/** The Server MUST respond with the 403 Forbidden status to PATCH requests against a upload URL */
public class PatchOnFinalUploadNotAllowedException extends TusException {
- public PatchOnFinalUploadNotAllowedException(String message) {
- super(HttpServletResponse.SC_FORBIDDEN, message);
- }
+ public PatchOnFinalUploadNotAllowedException(String message) {
+ super(HttpServletResponse.SC_FORBIDDEN, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/PostOnInvalidRequestURIException.java b/src/main/java/me/desair/tus/server/exception/PostOnInvalidRequestURIException.java
index 1ef29d6..3e4d16a 100644
--- a/src/main/java/me/desair/tus/server/exception/PostOnInvalidRequestURIException.java
+++ b/src/main/java/me/desair/tus/server/exception/PostOnInvalidRequestURIException.java
@@ -2,12 +2,10 @@
import jakarta.servlet.http.HttpServletResponse;
-/**
- * Exception thrown when a POST request was received on an invalid URI
- */
+/** Exception thrown when a POST request was received on an invalid URI */
public class PostOnInvalidRequestURIException extends TusException {
- public PostOnInvalidRequestURIException(String message) {
- super(HttpServletResponse.SC_METHOD_NOT_ALLOWED, message);
- }
+ public PostOnInvalidRequestURIException(String message) {
+ super(HttpServletResponse.SC_METHOD_NOT_ALLOWED, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/TusException.java b/src/main/java/me/desair/tus/server/exception/TusException.java
index d0bc66f..7ba43b9 100644
--- a/src/main/java/me/desair/tus/server/exception/TusException.java
+++ b/src/main/java/me/desair/tus/server/exception/TusException.java
@@ -1,22 +1,20 @@
package me.desair.tus.server.exception;
-/**
- * Super class for exception in the tus protocol
- */
+/** Super class for exception in the tus protocol */
public class TusException extends Exception {
- private int status;
+ private int status;
- public TusException(int status, String message) {
- this(status, message, null);
- }
+ public TusException(int status, String message) {
+ this(status, message, null);
+ }
- public TusException(int status, String message, Throwable e) {
- super(message, e);
- this.status = status;
- }
+ public TusException(int status, String message, Throwable e) {
+ super(message, e);
+ this.status = status;
+ }
- public int getStatus() {
- return status;
- }
+ public int getStatus() {
+ return status;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/UnsupportedMethodException.java b/src/main/java/me/desair/tus/server/exception/UnsupportedMethodException.java
index eb9b8a0..5a9780b 100644
--- a/src/main/java/me/desair/tus/server/exception/UnsupportedMethodException.java
+++ b/src/main/java/me/desair/tus/server/exception/UnsupportedMethodException.java
@@ -2,11 +2,9 @@
import jakarta.servlet.http.HttpServletResponse;
-/**
- * Exception thrown when we receive a HTTP request with a method name that we do not support
- */
+/** Exception thrown when we receive a HTTP request with a method name that we do not support */
public class UnsupportedMethodException extends TusException {
- public UnsupportedMethodException(String message) {
- super(HttpServletResponse.SC_METHOD_NOT_ALLOWED, message);
- }
+ public UnsupportedMethodException(String message) {
+ super(HttpServletResponse.SC_METHOD_NOT_ALLOWED, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/UploadAlreadyLockedException.java b/src/main/java/me/desair/tus/server/exception/UploadAlreadyLockedException.java
index 784c88f..74c9900 100644
--- a/src/main/java/me/desair/tus/server/exception/UploadAlreadyLockedException.java
+++ b/src/main/java/me/desair/tus/server/exception/UploadAlreadyLockedException.java
@@ -1,8 +1,8 @@
package me.desair.tus.server.exception;
public class UploadAlreadyLockedException extends TusException {
- public UploadAlreadyLockedException(String message) {
- // 423 is LOCKED (WebDAV rfc 4918)
- super(423, message);
- }
+ public UploadAlreadyLockedException(String message) {
+ // 423 is LOCKED (WebDAV rfc 4918)
+ super(423, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/UploadChecksumMismatchException.java b/src/main/java/me/desair/tus/server/exception/UploadChecksumMismatchException.java
index b8a65b5..cd67529 100644
--- a/src/main/java/me/desair/tus/server/exception/UploadChecksumMismatchException.java
+++ b/src/main/java/me/desair/tus/server/exception/UploadChecksumMismatchException.java
@@ -1,10 +1,11 @@
package me.desair.tus.server.exception;
/**
- * Exception thrown when the client provided checksum does not match the checksum calculated by the server
+ * Exception thrown when the client provided checksum does not match the checksum calculated by the
+ * server
*/
public class UploadChecksumMismatchException extends TusException {
- public UploadChecksumMismatchException(String message) {
- super(460, message);
- }
+ public UploadChecksumMismatchException(String message) {
+ super(460, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/UploadInProgressException.java b/src/main/java/me/desair/tus/server/exception/UploadInProgressException.java
index db43f0f..eee5565 100644
--- a/src/main/java/me/desair/tus/server/exception/UploadInProgressException.java
+++ b/src/main/java/me/desair/tus/server/exception/UploadInProgressException.java
@@ -1,13 +1,13 @@
package me.desair.tus.server.exception;
/**
- * Exception thrown when accessing an upload that is still in progress and this
- * is not supported by the operation
+ * Exception thrown when accessing an upload that is still in progress and this is not supported by
+ * the operation
*/
public class UploadInProgressException extends TusException {
- public UploadInProgressException(String message) {
- //422 Unprocessable Entity
- //The request was well-formed but was unable to be followed due to semantic errors.
- super(422, message);
- }
+ public UploadInProgressException(String message) {
+ // 422 Unprocessable Entity
+ // The request was well-formed but was unable to be followed due to semantic errors.
+ super(422, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/UploadLengthNotAllowedOnConcatenationException.java b/src/main/java/me/desair/tus/server/exception/UploadLengthNotAllowedOnConcatenationException.java
index 3e97b67..13d974f 100644
--- a/src/main/java/me/desair/tus/server/exception/UploadLengthNotAllowedOnConcatenationException.java
+++ b/src/main/java/me/desair/tus/server/exception/UploadLengthNotAllowedOnConcatenationException.java
@@ -2,11 +2,9 @@
import jakarta.servlet.http.HttpServletResponse;
-/**
- * Exception thrown when the Client includes the Upload-Length header in the upload creation.
- */
+/** Exception thrown when the Client includes the Upload-Length header in the upload creation. */
public class UploadLengthNotAllowedOnConcatenationException extends TusException {
- public UploadLengthNotAllowedOnConcatenationException(String message) {
- super(HttpServletResponse.SC_BAD_REQUEST, message);
- }
+ public UploadLengthNotAllowedOnConcatenationException(String message) {
+ super(HttpServletResponse.SC_BAD_REQUEST, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/UploadNotFoundException.java b/src/main/java/me/desair/tus/server/exception/UploadNotFoundException.java
index bd85c4e..bbc270a 100644
--- a/src/main/java/me/desair/tus/server/exception/UploadNotFoundException.java
+++ b/src/main/java/me/desair/tus/server/exception/UploadNotFoundException.java
@@ -2,13 +2,14 @@
import jakarta.servlet.http.HttpServletResponse;
-/** Exception thrown when the given upload ID was not found
- *
- * If the resource is not found, the Server SHOULD return either the
- * 404 Not Found, 410 Gone or 403 Forbidden status without the Upload-Offset header.
+/**
+ * Exception thrown when the given upload ID was not found
+ *
+ * If the resource is not found, the Server SHOULD return either the 404 Not Found, 410 Gone or
+ * 403 Forbidden status without the Upload-Offset header.
*/
public class UploadNotFoundException extends TusException {
- public UploadNotFoundException(String message) {
- super(HttpServletResponse.SC_NOT_FOUND, message);
- }
+ public UploadNotFoundException(String message) {
+ super(HttpServletResponse.SC_NOT_FOUND, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/exception/UploadOffsetMismatchException.java b/src/main/java/me/desair/tus/server/exception/UploadOffsetMismatchException.java
index 3bb541b..bde3057 100644
--- a/src/main/java/me/desair/tus/server/exception/UploadOffsetMismatchException.java
+++ b/src/main/java/me/desair/tus/server/exception/UploadOffsetMismatchException.java
@@ -3,11 +3,11 @@
import jakarta.servlet.http.HttpServletResponse;
/**
- * If the offsets do not match, the Server MUST respond with the
- * 409 Conflict status without modifying the upload resource.
+ * If the offsets do not match, the Server MUST respond with the 409 Conflict status without
+ * modifying the upload resource.
*/
public class UploadOffsetMismatchException extends TusException {
- public UploadOffsetMismatchException(String message) {
- super(HttpServletResponse.SC_CONFLICT, message);
- }
+ public UploadOffsetMismatchException(String message) {
+ super(HttpServletResponse.SC_CONFLICT, message);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/expiration/ExpirationExtension.java b/src/main/java/me/desair/tus/server/expiration/ExpirationExtension.java
index 3be2bbe..2723c9f 100644
--- a/src/main/java/me/desair/tus/server/expiration/ExpirationExtension.java
+++ b/src/main/java/me/desair/tus/server/expiration/ExpirationExtension.java
@@ -3,35 +3,32 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
-
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestHandler;
import me.desair.tus.server.RequestValidator;
import me.desair.tus.server.util.AbstractTusExtension;
-/**
- * The Server MAY remove unfinished uploads once they expire.
- */
+/** The Server MAY remove unfinished uploads once they expire. */
public class ExpirationExtension extends AbstractTusExtension {
- @Override
- public String getName() {
- return "expiration";
- }
+ @Override
+ public String getName() {
+ return "expiration";
+ }
- @Override
- public Collection getMinimalSupportedHttpMethods() {
- return Arrays.asList(HttpMethod.OPTIONS, HttpMethod.PATCH, HttpMethod.POST);
- }
+ @Override
+ public Collection getMinimalSupportedHttpMethods() {
+ return Arrays.asList(HttpMethod.OPTIONS, HttpMethod.PATCH, HttpMethod.POST);
+ }
- @Override
- protected void initValidators(List requestValidators) {
- //No validators
- }
+ @Override
+ protected void initValidators(List requestValidators) {
+ // No validators
+ }
- @Override
- protected void initRequestHandlers(List requestHandlers) {
- requestHandlers.add(new ExpirationOptionsRequestHandler());
- requestHandlers.add(new ExpirationRequestHandler());
- }
+ @Override
+ protected void initRequestHandlers(List requestHandlers) {
+ requestHandlers.add(new ExpirationOptionsRequestHandler());
+ requestHandlers.add(new ExpirationRequestHandler());
+ }
}
diff --git a/src/main/java/me/desair/tus/server/expiration/ExpirationOptionsRequestHandler.java b/src/main/java/me/desair/tus/server/expiration/ExpirationOptionsRequestHandler.java
index 3225165..e126ef1 100644
--- a/src/main/java/me/desair/tus/server/expiration/ExpirationOptionsRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/expiration/ExpirationOptionsRequestHandler.java
@@ -3,14 +3,13 @@
import me.desair.tus.server.util.AbstractExtensionRequestHandler;
/**
- * The Server MAY remove unfinished uploads once they expire. In order to indicate this behavior to the Client,
- * the Server MUST add expiration to the Tus-Extension header.
+ * The Server MAY remove unfinished uploads once they expire. In order to indicate this behavior to
+ * the Client, the Server MUST add expiration to the Tus-Extension header.
*/
public class ExpirationOptionsRequestHandler extends AbstractExtensionRequestHandler {
- @Override
- protected void appendExtensions(StringBuilder extensionBuilder) {
- addExtension(extensionBuilder, "expiration");
- }
-
+ @Override
+ protected void appendExtensions(StringBuilder extensionBuilder) {
+ addExtension(extensionBuilder, "expiration");
+ }
}
diff --git a/src/main/java/me/desair/tus/server/expiration/ExpirationRequestHandler.java b/src/main/java/me/desair/tus/server/expiration/ExpirationRequestHandler.java
index 0326f58..c010313 100644
--- a/src/main/java/me/desair/tus/server/expiration/ExpirationRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/expiration/ExpirationRequestHandler.java
@@ -1,7 +1,6 @@
package me.desair.tus.server.expiration;
import java.io.IOException;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.TusException;
@@ -13,50 +12,58 @@
import org.apache.commons.lang3.StringUtils;
/**
- * The Upload-Expires response header indicates the time after which the unfinished upload expires. This header MUST
- * be included in every PATCH response if the upload is going to expire. Its value MAY change over time.
- * If the expiration is known at the creation, the Upload-Expires header MUST be included in the response to
- * the initial POST request. Its value MAY change over time. The value of the Upload-Expires header MUST be in
- * RFC 7231 (https://tools.ietf.org/html/rfc7231#section-7.1.1.1) datetime format.
+ * The Upload-Expires response header indicates the time after which the unfinished upload expires.
+ * This header MUST be included in every PATCH response if the upload is going to expire. Its value
+ * MAY change over time. If the expiration is known at the creation, the Upload-Expires header MUST
+ * be included in the response to the initial POST request. Its value MAY change over time. The
+ * value of the Upload-Expires header MUST be in RFC 7231
+ * (https://tools.ietf.org/html/rfc7231#section-7.1.1.1) datetime format.
*/
public class ExpirationRequestHandler extends AbstractRequestHandler {
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.PATCH.equals(method)
- || HttpMethod.POST.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.PATCH.equals(method) || HttpMethod.POST.equals(method);
+ }
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException, TusException {
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
- //For post requests, the upload URI is part of the response
- String uploadUri = servletResponse.getHeader(HttpHeader.LOCATION);
- if (StringUtils.isBlank(uploadUri)) {
- //For patch request, our upload URI is the URI of the request
- uploadUri = servletRequest.getRequestURI();
- }
+ // For post requests, the upload URI is part of the response
+ String uploadUri = servletResponse.getHeader(HttpHeader.LOCATION);
+ if (StringUtils.isBlank(uploadUri)) {
+ // For patch request, our upload URI is the URI of the request
+ uploadUri = servletRequest.getRequestURI();
+ }
- Long expirationPeriod = uploadStorageService.getUploadExpirationPeriod();
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(uploadUri, ownerKey);
+ Long expirationPeriod = uploadStorageService.getUploadExpirationPeriod();
+ UploadInfo uploadInfo = uploadStorageService.getUploadInfo(uploadUri, ownerKey);
- // The Upload-Expires response header MUST be included in every PATCH response if the upload is going to expire.
- // If the expiration is known at the creation, the Upload-Expires header MUST be included in the response to
- // the initial POST request. Its value MAY change over time.
+ // The Upload-Expires response header MUST be included in every PATCH response if the upload
+ // is
+ // going to expire.
+ // If the expiration is known at the creation, the Upload-Expires header MUST be included in
+ // the
+ // response to
+ // the initial POST request. Its value MAY change over time.
- if (expirationPeriod != null && expirationPeriod > 0 && uploadInfo != null) {
+ if (expirationPeriod != null && expirationPeriod > 0 && uploadInfo != null) {
- uploadInfo.updateExpiration(expirationPeriod);
- uploadStorageService.update(uploadInfo);
+ uploadInfo.updateExpiration(expirationPeriod);
+ uploadStorageService.update(uploadInfo);
- servletResponse.setDateHeader(HttpHeader.UPLOAD_EXPIRES, uploadInfo.getExpirationTimestamp());
- }
+ servletResponse.setDateHeader(HttpHeader.UPLOAD_EXPIRES, uploadInfo.getExpirationTimestamp());
}
+ }
- @Override
- public boolean isErrorHandler() {
- return true;
- }
+ @Override
+ public boolean isErrorHandler() {
+ return true;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/termination/TerminationDeleteRequestHandler.java b/src/main/java/me/desair/tus/server/termination/TerminationDeleteRequestHandler.java
index aaee961..7b61176 100644
--- a/src/main/java/me/desair/tus/server/termination/TerminationDeleteRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/termination/TerminationDeleteRequestHandler.java
@@ -1,8 +1,7 @@
package me.desair.tus.server.termination;
-import java.io.IOException;
import jakarta.servlet.http.HttpServletResponse;
-
+import java.io.IOException;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.TusException;
import me.desair.tus.server.upload.UploadInfo;
@@ -12,29 +11,34 @@
import me.desair.tus.server.util.TusServletResponse;
/**
- * When receiving a DELETE request for an existing upload the Server SHOULD free associated resources
- * and MUST respond with the 204 No Content status confirming that the upload was terminated. For all future requests
- * to this URL the Server SHOULD respond with the 404 Not Found or 410 Gone status.
+ * When receiving a DELETE request for an existing upload the Server SHOULD free associated
+ * resources and MUST respond with the 204 No Content status confirming that the upload was
+ * terminated. For all future requests to this URL the Server SHOULD respond with the 404 Not Found
+ * or 410 Gone status.
*/
public class TerminationDeleteRequestHandler extends AbstractRequestHandler {
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.DELETE.equals(method);
- }
-
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException, TusException {
-
- UploadInfo uploadInfo = uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
-
- if (uploadInfo != null) {
- uploadStorageService.terminateUpload(uploadInfo);
- }
-
- servletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.DELETE.equals(method);
+ }
+
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
+
+ UploadInfo uploadInfo =
+ uploadStorageService.getUploadInfo(servletRequest.getRequestURI(), ownerKey);
+
+ if (uploadInfo != null) {
+ uploadStorageService.terminateUpload(uploadInfo);
}
+ servletResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/termination/TerminationExtension.java b/src/main/java/me/desair/tus/server/termination/TerminationExtension.java
index c9ebffb..2a8f85f 100644
--- a/src/main/java/me/desair/tus/server/termination/TerminationExtension.java
+++ b/src/main/java/me/desair/tus/server/termination/TerminationExtension.java
@@ -3,39 +3,38 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
-
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestHandler;
import me.desair.tus.server.RequestValidator;
import me.desair.tus.server.util.AbstractTusExtension;
/**
- * This extension defines a way for the Client to terminate completed and unfinished
- * uploads allowing the Server to free up used resources.
- *
- * If this extension is supported by the Server, it MUST be announced by adding "termination"
- * to the Tus-Extension header.
+ * This extension defines a way for the Client to terminate completed and unfinished uploads
+ * allowing the Server to free up used resources.
+ *
+ * If this extension is supported by the Server, it MUST be announced by adding "termination" to
+ * the Tus-Extension header.
*/
public class TerminationExtension extends AbstractTusExtension {
- @Override
- public String getName() {
- return "termination";
- }
+ @Override
+ public String getName() {
+ return "termination";
+ }
- @Override
- public Collection getMinimalSupportedHttpMethods() {
- return Arrays.asList(HttpMethod.OPTIONS, HttpMethod.DELETE);
- }
+ @Override
+ public Collection getMinimalSupportedHttpMethods() {
+ return Arrays.asList(HttpMethod.OPTIONS, HttpMethod.DELETE);
+ }
- @Override
- protected void initValidators(List requestValidators) {
- //All validation is all read done by the Core protocol
- }
+ @Override
+ protected void initValidators(List requestValidators) {
+ // All validation is all read done by the Core protocol
+ }
- @Override
- protected void initRequestHandlers(List requestHandlers) {
- requestHandlers.add(new TerminationDeleteRequestHandler());
- requestHandlers.add(new TerminationOptionsRequestHandler());
- }
+ @Override
+ protected void initRequestHandlers(List requestHandlers) {
+ requestHandlers.add(new TerminationDeleteRequestHandler());
+ requestHandlers.add(new TerminationOptionsRequestHandler());
+ }
}
diff --git a/src/main/java/me/desair/tus/server/termination/TerminationOptionsRequestHandler.java b/src/main/java/me/desair/tus/server/termination/TerminationOptionsRequestHandler.java
index 03c3422..6c0f1d3 100644
--- a/src/main/java/me/desair/tus/server/termination/TerminationOptionsRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/termination/TerminationOptionsRequestHandler.java
@@ -2,14 +2,11 @@
import me.desair.tus.server.util.AbstractExtensionRequestHandler;
-/**
- * Add our download extension the Tus-Extension header
- */
+/** Add our download extension the Tus-Extension header */
public class TerminationOptionsRequestHandler extends AbstractExtensionRequestHandler {
- @Override
- protected void appendExtensions(StringBuilder extensionBuilder) {
- addExtension(extensionBuilder, "termination");
- }
-
+ @Override
+ protected void appendExtensions(StringBuilder extensionBuilder) {
+ addExtension(extensionBuilder, "termination");
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/TimeBasedUploadIdFactory.java b/src/main/java/me/desair/tus/server/upload/TimeBasedUploadIdFactory.java
index ea56dad..8b98ad2 100644
--- a/src/main/java/me/desair/tus/server/upload/TimeBasedUploadIdFactory.java
+++ b/src/main/java/me/desair/tus/server/upload/TimeBasedUploadIdFactory.java
@@ -1,33 +1,32 @@
package me.desair.tus.server.upload;
import java.io.Serializable;
-
import org.apache.commons.lang3.StringUtils;
/**
- * Alternative {@link UploadIdFactory} implementation that uses the current system time to generate ID's.
- * Since time is not unique, this upload ID factory should not be used in busy, clustered production systems.
+ * Alternative {@link UploadIdFactory} implementation that uses the current system time to generate
+ * ID's. Since time is not unique, this upload ID factory should not be used in busy, clustered
+ * production systems.
*/
public class TimeBasedUploadIdFactory extends UploadIdFactory {
- @Override
- protected Serializable getIdValueIfValid(String extractedUrlId) {
- Long id = null;
-
- if (StringUtils.isNotBlank(extractedUrlId)) {
- try {
- id = Long.parseLong(extractedUrlId);
- } catch (NumberFormatException ex) {
- id = null;
- }
- }
+ @Override
+ protected Serializable getIdValueIfValid(String extractedUrlId) {
+ Long id = null;
- return id;
+ if (StringUtils.isNotBlank(extractedUrlId)) {
+ try {
+ id = Long.parseLong(extractedUrlId);
+ } catch (NumberFormatException ex) {
+ id = null;
+ }
}
- @Override
- public synchronized UploadId createId() {
- return new UploadId(System.currentTimeMillis());
- }
+ return id;
+ }
+ @Override
+ public synchronized UploadId createId() {
+ return new UploadId(System.currentTimeMillis());
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/UUIDUploadIdFactory.java b/src/main/java/me/desair/tus/server/upload/UUIDUploadIdFactory.java
index cce50a6..674a222 100644
--- a/src/main/java/me/desair/tus/server/upload/UUIDUploadIdFactory.java
+++ b/src/main/java/me/desair/tus/server/upload/UUIDUploadIdFactory.java
@@ -4,26 +4,25 @@
import java.util.UUID;
/**
- * Factory to create unique upload IDs. This factory can also parse the upload identifier
- * from a given upload URL.
+ * Factory to create unique upload IDs. This factory can also parse the upload identifier from a
+ * given upload URL.
*/
public class UUIDUploadIdFactory extends UploadIdFactory {
- @Override
- protected Serializable getIdValueIfValid(String extractedUrlId) {
- UUID id = null;
- try {
- id = UUID.fromString(extractedUrlId);
- } catch (IllegalArgumentException ex) {
- id = null;
- }
-
- return id;
+ @Override
+ protected Serializable getIdValueIfValid(String extractedUrlId) {
+ UUID id = null;
+ try {
+ id = UUID.fromString(extractedUrlId);
+ } catch (IllegalArgumentException ex) {
+ id = null;
}
- @Override
- public synchronized UploadId createId() {
- return new UploadId(UUID.randomUUID());
- }
+ return id;
+ }
+ @Override
+ public synchronized UploadId createId() {
+ return new UploadId(UUID.randomUUID());
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/UploadId.java b/src/main/java/me/desair/tus/server/upload/UploadId.java
index 83bd392..b93015e 100644
--- a/src/main/java/me/desair/tus/server/upload/UploadId.java
+++ b/src/main/java/me/desair/tus/server/upload/UploadId.java
@@ -3,78 +3,77 @@
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Objects;
-
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.net.URLCodec;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * The unique identifier of an upload process in the tus protocol
- */
+/** The unique identifier of an upload process in the tus protocol */
public class UploadId implements Serializable {
- private static final String UPLOAD_ID_CHARSET = "UTF-8";
- private static final Logger log = LoggerFactory.getLogger(UploadId.class);
-
- private String urlSafeValue;
- private Serializable originalObject;
+ private static final String UPLOAD_ID_CHARSET = "UTF-8";
+ private static final Logger log = LoggerFactory.getLogger(UploadId.class);
- /**
- * Create a new {@link UploadId} instance based on the provided object using it's toString method.
- * @param inputObject The object to use for constructing the ID
- */
- public UploadId(Serializable inputObject) {
- String inputValue = (inputObject == null ? null : inputObject.toString());
- Validate.notBlank(inputValue, "The upload ID value cannot be blank");
+ private String urlSafeValue;
+ private Serializable originalObject;
- this.originalObject = inputObject;
- URLCodec codec = new URLCodec();
- //Check if value is not encoded already
- try {
- if (inputValue != null && inputValue.equals(codec.decode(inputValue, UPLOAD_ID_CHARSET))) {
- this.urlSafeValue = codec.encode(inputValue, UPLOAD_ID_CHARSET);
- } else {
- //value is already encoded, use as is
- this.urlSafeValue = inputValue;
- }
- } catch (DecoderException | UnsupportedEncodingException e) {
- log.warn("Unable to URL encode upload ID value", e);
- this.urlSafeValue = inputValue;
- }
- }
+ /**
+ * Create a new {@link UploadId} instance based on the provided object using it's toString method.
+ *
+ * @param inputObject The object to use for constructing the ID
+ */
+ public UploadId(Serializable inputObject) {
+ String inputValue = (inputObject == null ? null : inputObject.toString());
+ Validate.notBlank(inputValue, "The upload ID value cannot be blank");
- /**
- * The original input object that was provided when constructing this upload ID
- * @return The original object used to create this ID
- */
- public Serializable getOriginalObject() {
- return this.originalObject;
+ this.originalObject = inputObject;
+ URLCodec codec = new URLCodec();
+ // Check if value is not encoded already
+ try {
+ if (inputValue != null && inputValue.equals(codec.decode(inputValue, UPLOAD_ID_CHARSET))) {
+ this.urlSafeValue = codec.encode(inputValue, UPLOAD_ID_CHARSET);
+ } else {
+ // value is already encoded, use as is
+ this.urlSafeValue = inputValue;
+ }
+ } catch (DecoderException | UnsupportedEncodingException e) {
+ log.warn("Unable to URL encode upload ID value", e);
+ this.urlSafeValue = inputValue;
}
+ }
- @Override
- public String toString() {
- return urlSafeValue;
- }
+ /**
+ * The original input object that was provided when constructing this upload ID
+ *
+ * @return The original object used to create this ID
+ */
+ public Serializable getOriginalObject() {
+ return this.originalObject;
+ }
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof UploadId)) {
- return false;
- }
+ @Override
+ public String toString() {
+ return urlSafeValue;
+ }
- UploadId uploadId = (UploadId) o;
- //Upload IDs with the same URL-safe value should be considered equal
- return Objects.equals(urlSafeValue, uploadId.urlSafeValue);
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
}
-
- @Override
- public int hashCode() {
- //Upload IDs with the same URL-safe value should be considered equal
- return Objects.hash(urlSafeValue);
+ if (!(o instanceof UploadId)) {
+ return false;
}
+
+ UploadId uploadId = (UploadId) o;
+ // Upload IDs with the same URL-safe value should be considered equal
+ return Objects.equals(urlSafeValue, uploadId.urlSafeValue);
+ }
+
+ @Override
+ public int hashCode() {
+ // Upload IDs with the same URL-safe value should be considered equal
+ return Objects.hash(urlSafeValue);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/UploadIdFactory.java b/src/main/java/me/desair/tus/server/upload/UploadIdFactory.java
index 791f00c..1207b25 100644
--- a/src/main/java/me/desair/tus/server/upload/UploadIdFactory.java
+++ b/src/main/java/me/desair/tus/server/upload/UploadIdFactory.java
@@ -3,88 +3,92 @@
import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
/**
- * Interface for a factory that can create unique upload IDs. This factory can also parse the upload identifier
- * from a given upload URL.
+ * Interface for a factory that can create unique upload IDs. This factory can also parse the upload
+ * identifier from a given upload URL.
*/
public abstract class UploadIdFactory {
- private String uploadURI = "/";
- private Pattern uploadUriPattern = null;
+ private String uploadURI = "/";
+ private Pattern uploadUriPattern = null;
- /**
- * Set the URI under which the main tus upload endpoint is hosted.
- * Optionally, this URI may contain regex parameters in order to support endpoints that contain
- * URL parameters, for example /users/[0-9]+/files/upload
- *
- * @param uploadURI The URI of the main tus upload endpoint
- */
- public void setUploadURI(String uploadURI) {
- Validate.notBlank(uploadURI, "The upload URI pattern cannot be blank");
- Validate.isTrue(StringUtils.startsWith(uploadURI, "/"), "The upload URI should start with /");
- Validate.isTrue(!StringUtils.endsWith(uploadURI, "$"), "The upload URI should not end with $");
- this.uploadURI = uploadURI;
- this.uploadUriPattern = null;
- }
+ /**
+ * Set the URI under which the main tus upload endpoint is hosted. Optionally, this URI may
+ * contain regex parameters in order to support endpoints that contain URL parameters, for example
+ * /users/[0-9]+/files/upload
+ *
+ * @param uploadURI The URI of the main tus upload endpoint
+ */
+ public void setUploadURI(String uploadURI) {
+ Validate.notBlank(uploadURI, "The upload URI pattern cannot be blank");
+ Validate.isTrue(StringUtils.startsWith(uploadURI, "/"), "The upload URI should start with /");
+ Validate.isTrue(!StringUtils.endsWith(uploadURI, "$"), "The upload URI should not end with $");
+ this.uploadURI = uploadURI;
+ this.uploadUriPattern = null;
+ }
- /**
- * Return the URI of the main tus upload endpoint. Note that this value possibly contains regex parameters.
- * @return The URI of the main tus upload endpoint.
- */
- public String getUploadURI() {
- return uploadURI;
- }
+ /**
+ * Return the URI of the main tus upload endpoint. Note that this value possibly contains regex
+ * parameters.
+ *
+ * @return The URI of the main tus upload endpoint.
+ */
+ public String getUploadURI() {
+ return uploadURI;
+ }
- /**
- * Read the upload identifier from the given URL.
- *
- * Clients will send requests to upload URLs or provided URLs of completed uploads. This method is able to
- * parse those URLs and provide the user with the corresponding upload ID.
- *
- * @param url The URL provided by the client
- * @return The corresponding Upload identifier
- */
- public UploadId readUploadId(String url) {
- Matcher uploadUriMatcher = getUploadUriPattern().matcher(StringUtils.trimToEmpty(url));
- String pathId = uploadUriMatcher.replaceFirst("");
+ /**
+ * Read the upload identifier from the given URL.
+ *
+ * Clients will send requests to upload URLs or provided URLs of completed uploads. This method
+ * is able to parse those URLs and provide the user with the corresponding upload ID.
+ *
+ * @param url The URL provided by the client
+ * @return The corresponding Upload identifier
+ */
+ public UploadId readUploadId(String url) {
+ Matcher uploadUriMatcher = getUploadUriPattern().matcher(StringUtils.trimToEmpty(url));
+ String pathId = uploadUriMatcher.replaceFirst("");
- Serializable idValue = null;
- if (StringUtils.isNotBlank(pathId)) {
- idValue = getIdValueIfValid(pathId);
- }
-
- return idValue == null ? null : new UploadId(idValue);
+ Serializable idValue = null;
+ if (StringUtils.isNotBlank(pathId)) {
+ idValue = getIdValueIfValid(pathId);
}
- /**
- * Create a new unique upload ID
- * @return A new unique upload ID
- */
- public abstract UploadId createId();
+ return idValue == null ? null : new UploadId(idValue);
+ }
+
+ /**
+ * Create a new unique upload ID
+ *
+ * @return A new unique upload ID
+ */
+ public abstract UploadId createId();
- /**
- * Transform the extracted path ID value to a value to use for the upload ID object.
- * If the extracted value is not valid, null is returned
- * @param extractedUrlId The ID extracted from the URL
- * @return Value to use in the UploadId object, null if the extracted URL value was not valid
- */
- protected abstract Serializable getIdValueIfValid(String extractedUrlId);
+ /**
+ * Transform the extracted path ID value to a value to use for the upload ID object. If the
+ * extracted value is not valid, null is returned
+ *
+ * @param extractedUrlId The ID extracted from the URL
+ * @return Value to use in the UploadId object, null if the extracted URL value was not valid
+ */
+ protected abstract Serializable getIdValueIfValid(String extractedUrlId);
- /**
- * Build and retrieve the Upload URI regex pattern
- * @return A (cached) Pattern to match upload URI's
- */
- protected Pattern getUploadUriPattern() {
- if (uploadUriPattern == null) {
- //We will extract the upload ID's by removing the upload URI from the start of the request URI
- uploadUriPattern = Pattern.compile("^.*"
- + uploadURI
- + (StringUtils.endsWith(uploadURI, "/") ? "" : "/?"));
- }
- return uploadUriPattern;
+ /**
+ * Build and retrieve the Upload URI regex pattern
+ *
+ * @return A (cached) Pattern to match upload URI's
+ */
+ protected Pattern getUploadUriPattern() {
+ if (uploadUriPattern == null) {
+ // We will extract the upload ID's by removing the upload URI from the start of the
+ // request URI
+ uploadUriPattern =
+ Pattern.compile("^.*" + uploadURI + (StringUtils.endsWith(uploadURI, "/") ? "" : "/?"));
}
+ return uploadUriPattern;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/UploadInfo.java b/src/main/java/me/desair/tus/server/upload/UploadInfo.java
index c91f83b..4f1307f 100644
--- a/src/main/java/me/desair/tus/server/upload/UploadInfo.java
+++ b/src/main/java/me/desair/tus/server/upload/UploadInfo.java
@@ -1,13 +1,12 @@
package me.desair.tus.server.upload;
+import jakarta.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
-import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.util.Utils;
import org.apache.commons.codec.Charsets;
import org.apache.commons.codec.binary.Base64;
@@ -16,390 +15,417 @@
import org.apache.commons.lang3.builder.HashCodeBuilder;
/**
- * Class that contains all metadata on an upload process. This class also holds the metadata provided by the client
- * when creating the upload.
+ * Class that contains all metadata on an upload process. This class also holds the metadata
+ * provided by the client when creating the upload.
*/
public class UploadInfo implements Serializable {
- private static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
- private static List fileNameKeys = Arrays.asList("filename", "name");
- private static List mimeTypeKeys = Arrays.asList("mimetype", "filetype", "type");
-
- private UploadType uploadType;
- private Long offset;
- private String encodedMetadata;
- private Long length;
- private UploadId id;
- private String ownerKey;
- private Long creationTimestamp;
- private String creatorIpAddresses;
- private Long expirationTimestamp;
- private List concatenationPartIds;
- private String uploadConcatHeaderValue;
-
- /**
- * Default constructor to use if an upload is created without HTTP request
- */
- public UploadInfo() {
- creationTimestamp = getCurrentTime();
- offset = 0L;
- encodedMetadata = null;
- length = null;
- }
-
- /**
- * Constructor to use if the upload is created using an HTTP request (which is usually the case)
- * @param servletRequest The HTTP request that creates the new upload
- */
- public UploadInfo(HttpServletRequest servletRequest) {
- this();
- creatorIpAddresses = Utils.buildRemoteIpList(servletRequest);
- }
-
- /**
- * The current byte offset of the bytes that already have been stored for this upload on the server.
- * The offset is the position where the next newly received byte should be stored. This index is zero-based.
- * @return The offset where the next new byte will be written
- */
- public Long getOffset() {
- return offset;
- }
-
- /**
- * Set the position where the next newly received byte should be stored. This index is zero-based.
- * @param offset The offset where the next new byte should be written
- */
- public void setOffset(Long offset) {
- this.offset = offset;
- }
-
- /**
- * Get the encoded Tus metadata string as it was provided by the Tus client at creation of the upload.
- * The encoded metadata string consists of one or more comma-separated key-value pairs where the key is
- * ASCII encoded and the value Base64 encoded. See https://tus.io/protocols/resumable-upload.html#upload-metadata
- * @return The encoded metadata string as received from the client
- */
- public String getEncodedMetadata() {
- return encodedMetadata;
- }
-
- /**
- * Set the encoded Tus metadata string as it was provided by the Tus client at creation of the upload.
- * The encoded metadata string consists of one or more comma-separated key-value pairs where the key is
- * ASCII encoded and the value Base64 encoded. See https://tus.io/protocols/resumable-upload.html#upload-metadata
- * @return The encoded metadata string as received from the client
- */
- public void setEncodedMetadata(String encodedMetadata) {
- this.encodedMetadata = encodedMetadata;
- }
-
- /**
- * Get the decoded metadata map provided by the client based on the encoded Tus metadata string received on
- * creation of the upload. The encoded metadata string consists of one or more comma-separated key-value pairs
- * where the key is ASCII encoded and the value Base64 encoded. The key and value MUST be separated by a space.
- * See https://tus.io/protocols/resumable-upload.html#upload-metadata
- * @return The encoded metadata string as received from the client
- */
- public Map getMetadata() {
- Map metadata = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
- for (String valuePair : splitToArray(encodedMetadata, ",")) {
- String[] keyValue = splitToArray(valuePair, "\\s");
- String key = null;
- String value = null;
- if (keyValue.length > 0) {
- key = StringUtils.trimToEmpty(keyValue[0]);
-
- //Skip any blank values
- int i = 1;
- while (keyValue.length > i && StringUtils.isBlank(keyValue[i])) {
- i++;
- }
-
- if (keyValue.length > i) {
- value = decode(keyValue[i]);
- }
-
- metadata.put(key, value);
- }
+ private static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
+ private static List fileNameKeys = Arrays.asList("filename", "name");
+ private static List mimeTypeKeys = Arrays.asList("mimetype", "filetype", "type");
+
+ private UploadType uploadType;
+ private Long offset;
+ private String encodedMetadata;
+ private Long length;
+ private UploadId id;
+ private String ownerKey;
+ private Long creationTimestamp;
+ private String creatorIpAddresses;
+ private Long expirationTimestamp;
+ private List concatenationPartIds;
+ private String uploadConcatHeaderValue;
+
+ /** Default constructor to use if an upload is created without HTTP request */
+ public UploadInfo() {
+ creationTimestamp = getCurrentTime();
+ offset = 0L;
+ encodedMetadata = null;
+ length = null;
+ }
+
+ /**
+ * Constructor to use if the upload is created using an HTTP request (which is usually the case)
+ *
+ * @param servletRequest The HTTP request that creates the new upload
+ */
+ public UploadInfo(HttpServletRequest servletRequest) {
+ this();
+ creatorIpAddresses = Utils.buildRemoteIpList(servletRequest);
+ }
+
+ /**
+ * The current byte offset of the bytes that already have been stored for this upload on the
+ * server. The offset is the position where the next newly received byte should be stored. This
+ * index is zero-based.
+ *
+ * @return The offset where the next new byte will be written
+ */
+ public Long getOffset() {
+ return offset;
+ }
+
+ /**
+ * Set the position where the next newly received byte should be stored. This index is zero-based.
+ *
+ * @param offset The offset where the next new byte should be written
+ */
+ public void setOffset(Long offset) {
+ this.offset = offset;
+ }
+
+ /**
+ * Get the encoded Tus metadata string as it was provided by the Tus client at creation of the
+ * upload. The encoded metadata string consists of one or more comma-separated key-value pairs
+ * where the key is ASCII encoded and the value Base64 encoded. See
+ * https://tus.io/protocols/resumable-upload.html#upload-metadata
+ *
+ * @return The encoded metadata string as received from the client
+ */
+ public String getEncodedMetadata() {
+ return encodedMetadata;
+ }
+
+ /**
+ * Set the encoded Tus metadata string as it was provided by the Tus client at creation of the
+ * upload. The encoded metadata string consists of one or more comma-separated key-value pairs
+ * where the key is ASCII encoded and the value Base64 encoded. See
+ * https://tus.io/protocols/resumable-upload.html#upload-metadata
+ *
+ * @return The encoded metadata string as received from the client
+ */
+ public void setEncodedMetadata(String encodedMetadata) {
+ this.encodedMetadata = encodedMetadata;
+ }
+
+ /**
+ * Get the decoded metadata map provided by the client based on the encoded Tus metadata string
+ * received on creation of the upload. The encoded metadata string consists of one or more
+ * comma-separated key-value pairs where the key is ASCII encoded and the value Base64 encoded.
+ * The key and value MUST be separated by a space. See
+ * https://tus.io/protocols/resumable-upload.html#upload-metadata
+ *
+ * @return The encoded metadata string as received from the client
+ */
+ public Map getMetadata() {
+ Map metadata = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ for (String valuePair : splitToArray(encodedMetadata, ",")) {
+ String[] keyValue = splitToArray(valuePair, "\\s");
+ String key = null;
+ String value = null;
+ if (keyValue.length > 0) {
+ key = StringUtils.trimToEmpty(keyValue[0]);
+
+ // Skip any blank values
+ int i = 1;
+ while (keyValue.length > i && StringUtils.isBlank(keyValue[i])) {
+ i++;
}
- return metadata;
- }
-
- /**
- * Did the client provide any metadata when creating this upload?
- * @return True if metadata is present, false otherwise
- */
- public boolean hasMetadata() {
- return StringUtils.isNotBlank(encodedMetadata);
- }
-
- /**
- * Get the total length of the byte array that the client wants to upload. This value is provided by the client
- * when creating the upload (POST) or when uploading a new set of bytes (PATCH).
- * @return The number of bytes that the client specified he will upload
- */
- public Long getLength() {
- return length;
- }
- /**
- * Set the total length of the byte array that the client wants to upload. The client can provided this value
- * when creating the upload (POST) or when uploading a new set of bytes (PATCH).
- * @param length The number of bytes that the client specified he will upload
- */
- public void setLength(Long length) {
- this.length = (length != null && length > 0 ? length : null);
- }
-
- /**
- * Did the client already provide a total upload length?
- * @return True if the total upload length is known, false otherwise
- */
- public boolean hasLength() {
- return length != null;
- }
-
- /**
- * An upload is still in progress:
- * - as long as we did not receive information on the total length (see {@link UploadInfo#getLength()})
- * - the total length does not match the current offset
- * @return true if the upload is still in progress, false otherwise
- */
- public boolean isUploadInProgress() {
- return length == null || !offset.equals(length);
- }
-
- /**
- * Set the unique identifier of this upload process
- * The unique identifier is represented by a {@link UploadId} instance
- * @param id The unique identifier to use
- */
- public void setId(UploadId id) {
- this.id = id;
- }
-
- /**
- * Get the unique identifier of this upload process
- * The unique identifier is represented by a {@link UploadId} instance
- * @return The unique upload identifier of this upload
- */
- public UploadId getId() {
- return id;
- }
-
- /**
- * Set the owner key for this upload.
- * This key uniquely identifies the owner of the uploaded bytes. The user of this library is free to interpret the
- * meaning of "owner". This can be a user ID, a company division, a group of users, a tenant...
- * @param ownerKey The owner key to assign to this upload
- */
- public void setOwnerKey(String ownerKey) {
- this.ownerKey = ownerKey;
- }
-
- /**
- * Get the owner key for this upload.
- * This key uniquely identifies the owner of the uploaded bytes. The user of this library is free to interpret the
- * meaning of "owner". This can be a user ID, a company division, a group of users, a tenant...
- * @return The unique identifying key of the owner of this upload
- */
- public String getOwnerKey() {
- return ownerKey;
- }
-
- /**
- * Indicates the timestamp after which the upload expires in milliseconds since January 1, 1970, 00:00:00 GMT
- * @return The expiration timestamp in milliseconds
- */
- public Long getExpirationTimestamp() {
- return expirationTimestamp;
- }
-
- /**
- * Calculate the expiration timestamp based on the provided expiration period.
- * @param expirationPeriod The period the upload should remain valid
- */
- public void updateExpiration(long expirationPeriod) {
- expirationTimestamp = getCurrentTime() + expirationPeriod;
- }
-
- /**
- * The timestamp this upload was created in number of milliseconds since January 1, 1970, 00:00:00 GMT
- * @return Creation timestamp of this upload object
- */
- public Long getCreationTimestamp() {
- return creationTimestamp;
- }
-
- /**
- * Get the ip-addresses that were involved when this upload was created.
- * The returned value is a comma-separated list based on the remote address of the request and the
- * X-Forwareded-For header. The list is constructed as "client, proxy1, proxy2".
- * @return A comma-separated list of ip-addresses
- */
- public String getCreatorIpAddresses() {
- return creatorIpAddresses;
- }
-
- /**
- * Return the type of this upload. An upload can have types specified in {@link UploadType}.
- * The type of an upload depends on the Tus concatenation extension:
- * https://tus.io/protocols/resumable-upload.html#concatenation
- * @return The type of this upload as specified in {@link UploadType}
- */
- public UploadType getUploadType() {
- return uploadType;
- }
-
- /**
- * Set the type of this upload. An upload can have types specified in {@link UploadType}.
- * The type of an upload depends on the Tus concatenation extension:
- * https://tus.io/protocols/resumable-upload.html#concatenation
- * @param uploadType The type to set on this upload
- */
- public void setUploadType(UploadType uploadType) {
- this.uploadType = uploadType;
- }
-
- /**
- * Set the list of upload identifiers of which this upload is composed of.
- * @param concatenationPartIds The list of child upload identifiers
- */
- public void setConcatenationPartIds(List concatenationPartIds) {
- this.concatenationPartIds = concatenationPartIds;
- }
-
- /**
- * Get the list of upload identifiers of which this upload is composed of.
- * @return The list of child upload identifiers
- */
- public List getConcatenationPartIds() {
- return concatenationPartIds;
- }
-
- /**
- * Set the original value of the "Upload-Concat" HTTP header that was provided by the client
- * @param uploadConcatHeaderValue The original value of the "Upload-Concat" HTTP header
- */
- public void setUploadConcatHeaderValue(String uploadConcatHeaderValue) {
- this.uploadConcatHeaderValue = uploadConcatHeaderValue;
- }
-
- /**
- * Get the original value of the "Upload-Concat" HTTP header that was provided by the client
- * @return The original value of the "Upload-Concat" HTTP header
- */
- public String getUploadConcatHeaderValue() {
- return uploadConcatHeaderValue;
- }
-
- /**
- * Try to guess the filename of the uploaded data. If we cannot guess the name
- * we fall back to the ID.
- *
- * NOTE: This is only a guess, there are no guarantees that the return value is correct
- *
- * @return A potential file name
- */
- public String getFileName() {
- Map metadata = getMetadata();
- for (String fileNameKey : fileNameKeys) {
- if (metadata.containsKey(fileNameKey)) {
- return metadata.get(fileNameKey);
- }
- }
-
- return getId().toString();
- }
-
- /**
- * Try to guess the mime-type of the uploaded data.
- *
- * NOTE: This is only a guess, there are no guarantees that the return value is correct
- *
- * @return A potential file name
- */
- public String getFileMimeType() {
- Map metadata = getMetadata();
- for (String fileNameKey : mimeTypeKeys) {
- if (metadata.containsKey(fileNameKey)) {
- return metadata.get(fileNameKey);
- }
+ if (keyValue.length > i) {
+ value = decode(keyValue[i]);
}
- return APPLICATION_OCTET_STREAM;
- }
-
- /**
- * Check if this upload is expired
- * @return True if the upload is expired, false otherwise
- */
- public boolean isExpired() {
- return expirationTimestamp != null && expirationTimestamp < getCurrentTime();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (!(o instanceof UploadInfo)) {
- return false;
- }
-
- UploadInfo that = (UploadInfo) o;
-
- return new EqualsBuilder()
- .append(getUploadType(), that.getUploadType())
- .append(getOffset(), that.getOffset())
- .append(getEncodedMetadata(), that.getEncodedMetadata())
- .append(getLength(), that.getLength())
- .append(getId(), that.getId())
- .append(getOwnerKey(), that.getOwnerKey())
- .append(getCreatorIpAddresses(), that.getCreatorIpAddresses())
- .append(getExpirationTimestamp(), that.getExpirationTimestamp())
- .append(getConcatenationPartIds(), that.getConcatenationPartIds())
- .append(getUploadConcatHeaderValue(), that.getUploadConcatHeaderValue())
- .isEquals();
- }
-
- @Override
- public int hashCode() {
- return new HashCodeBuilder(17, 37)
- .append(getUploadType())
- .append(getOffset())
- .append(getEncodedMetadata())
- .append(getLength())
- .append(getId())
- .append(getOwnerKey())
- .append(getCreatorIpAddresses())
- .append(getExpirationTimestamp())
- .append(getConcatenationPartIds())
- .append(getUploadConcatHeaderValue())
- .toHashCode();
- }
-
- /**
- * Get the current time in the number of milliseconds since January 1, 1970, 00:00:00 GMT
- */
- protected long getCurrentTime() {
- return new Date().getTime();
- }
-
- private String[] splitToArray(String value, String separatorRegex) {
- if (StringUtils.isBlank(value)) {
- return new String[0];
- } else {
- return StringUtils.trimToEmpty(value).split(separatorRegex);
- }
- }
-
- private String decode(String encodedValue) {
- if (encodedValue == null) {
- return null;
- } else {
- return new String(Base64.decodeBase64(encodedValue), Charsets.UTF_8);
- }
- }
+ metadata.put(key, value);
+ }
+ }
+ return metadata;
+ }
+
+ /**
+ * Did the client provide any metadata when creating this upload?
+ *
+ * @return True if metadata is present, false otherwise
+ */
+ public boolean hasMetadata() {
+ return StringUtils.isNotBlank(encodedMetadata);
+ }
+
+ /**
+ * Get the total length of the byte array that the client wants to upload. This value is provided
+ * by the client when creating the upload (POST) or when uploading a new set of bytes (PATCH).
+ *
+ * @return The number of bytes that the client specified he will upload
+ */
+ public Long getLength() {
+ return length;
+ }
+
+ /**
+ * Set the total length of the byte array that the client wants to upload. The client can provided
+ * this value when creating the upload (POST) or when uploading a new set of bytes (PATCH).
+ *
+ * @param length The number of bytes that the client specified he will upload
+ */
+ public void setLength(Long length) {
+ this.length = (length != null && length > 0 ? length : null);
+ }
+
+ /**
+ * Did the client already provide a total upload length?
+ *
+ * @return True if the total upload length is known, false otherwise
+ */
+ public boolean hasLength() {
+ return length != null;
+ }
+
+ /**
+ * An upload is still in progress: - as long as we did not receive information on the total length
+ * (see {@link UploadInfo#getLength()}) - the total length does not match the current offset
+ *
+ * @return true if the upload is still in progress, false otherwise
+ */
+ public boolean isUploadInProgress() {
+ return length == null || !offset.equals(length);
+ }
+
+ /**
+ * Set the unique identifier of this upload process The unique identifier is represented by a
+ * {@link UploadId} instance
+ *
+ * @param id The unique identifier to use
+ */
+ public void setId(UploadId id) {
+ this.id = id;
+ }
+
+ /**
+ * Get the unique identifier of this upload process The unique identifier is represented by a
+ * {@link UploadId} instance
+ *
+ * @return The unique upload identifier of this upload
+ */
+ public UploadId getId() {
+ return id;
+ }
+
+ /**
+ * Set the owner key for this upload. This key uniquely identifies the owner of the uploaded
+ * bytes. The user of this library is free to interpret the meaning of "owner". This can be a user
+ * ID, a company division, a group of users, a tenant...
+ *
+ * @param ownerKey The owner key to assign to this upload
+ */
+ public void setOwnerKey(String ownerKey) {
+ this.ownerKey = ownerKey;
+ }
+
+ /**
+ * Get the owner key for this upload. This key uniquely identifies the owner of the uploaded
+ * bytes. The user of this library is free to interpret the meaning of "owner". This can be a user
+ * ID, a company division, a group of users, a tenant...
+ *
+ * @return The unique identifying key of the owner of this upload
+ */
+ public String getOwnerKey() {
+ return ownerKey;
+ }
+
+ /**
+ * Indicates the timestamp after which the upload expires in milliseconds since January 1, 1970,
+ * 00:00:00 GMT
+ *
+ * @return The expiration timestamp in milliseconds
+ */
+ public Long getExpirationTimestamp() {
+ return expirationTimestamp;
+ }
+
+ /**
+ * Calculate the expiration timestamp based on the provided expiration period.
+ *
+ * @param expirationPeriod The period the upload should remain valid
+ */
+ public void updateExpiration(long expirationPeriod) {
+ expirationTimestamp = getCurrentTime() + expirationPeriod;
+ }
+
+ /**
+ * The timestamp this upload was created in number of milliseconds since January 1, 1970, 00:00:00
+ * GMT
+ *
+ * @return Creation timestamp of this upload object
+ */
+ public Long getCreationTimestamp() {
+ return creationTimestamp;
+ }
+
+ /**
+ * Get the ip-addresses that were involved when this upload was created. The returned value is a
+ * comma-separated list based on the remote address of the request and the X-Forwareded-For
+ * header. The list is constructed as "client, proxy1, proxy2".
+ *
+ * @return A comma-separated list of ip-addresses
+ */
+ public String getCreatorIpAddresses() {
+ return creatorIpAddresses;
+ }
+
+ /**
+ * Return the type of this upload. An upload can have types specified in {@link UploadType}. The
+ * type of an upload depends on the Tus concatenation extension:
+ * https://tus.io/protocols/resumable-upload.html#concatenation
+ *
+ * @return The type of this upload as specified in {@link UploadType}
+ */
+ public UploadType getUploadType() {
+ return uploadType;
+ }
+
+ /**
+ * Set the type of this upload. An upload can have types specified in {@link UploadType}. The type
+ * of an upload depends on the Tus concatenation extension:
+ * https://tus.io/protocols/resumable-upload.html#concatenation
+ *
+ * @param uploadType The type to set on this upload
+ */
+ public void setUploadType(UploadType uploadType) {
+ this.uploadType = uploadType;
+ }
+
+ /**
+ * Set the list of upload identifiers of which this upload is composed of.
+ *
+ * @param concatenationPartIds The list of child upload identifiers
+ */
+ public void setConcatenationPartIds(List concatenationPartIds) {
+ this.concatenationPartIds = concatenationPartIds;
+ }
+
+ /**
+ * Get the list of upload identifiers of which this upload is composed of.
+ *
+ * @return The list of child upload identifiers
+ */
+ public List getConcatenationPartIds() {
+ return concatenationPartIds;
+ }
+
+ /**
+ * Set the original value of the "Upload-Concat" HTTP header that was provided by the client
+ *
+ * @param uploadConcatHeaderValue The original value of the "Upload-Concat" HTTP header
+ */
+ public void setUploadConcatHeaderValue(String uploadConcatHeaderValue) {
+ this.uploadConcatHeaderValue = uploadConcatHeaderValue;
+ }
+
+ /**
+ * Get the original value of the "Upload-Concat" HTTP header that was provided by the client
+ *
+ * @return The original value of the "Upload-Concat" HTTP header
+ */
+ public String getUploadConcatHeaderValue() {
+ return uploadConcatHeaderValue;
+ }
+
+ /**
+ * Try to guess the filename of the uploaded data. If we cannot guess the name we fall back to the
+ * ID.
+ *
+ * NOTE: This is only a guess, there are no guarantees that the return value is correct
+ *
+ * @return A potential file name
+ */
+ public String getFileName() {
+ Map metadata = getMetadata();
+ for (String fileNameKey : fileNameKeys) {
+ if (metadata.containsKey(fileNameKey)) {
+ return metadata.get(fileNameKey);
+ }
+ }
+
+ return getId().toString();
+ }
+
+ /**
+ * Try to guess the mime-type of the uploaded data.
+ *
+ * NOTE: This is only a guess, there are no guarantees that the return value is correct
+ *
+ * @return A potential file name
+ */
+ public String getFileMimeType() {
+ Map metadata = getMetadata();
+ for (String fileNameKey : mimeTypeKeys) {
+ if (metadata.containsKey(fileNameKey)) {
+ return metadata.get(fileNameKey);
+ }
+ }
+
+ return APPLICATION_OCTET_STREAM;
+ }
+
+ /**
+ * Check if this upload is expired
+ *
+ * @return True if the upload is expired, false otherwise
+ */
+ public boolean isExpired() {
+ return expirationTimestamp != null && expirationTimestamp < getCurrentTime();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof UploadInfo)) {
+ return false;
+ }
+
+ UploadInfo that = (UploadInfo) o;
+
+ return new EqualsBuilder()
+ .append(getUploadType(), that.getUploadType())
+ .append(getOffset(), that.getOffset())
+ .append(getEncodedMetadata(), that.getEncodedMetadata())
+ .append(getLength(), that.getLength())
+ .append(getId(), that.getId())
+ .append(getOwnerKey(), that.getOwnerKey())
+ .append(getCreatorIpAddresses(), that.getCreatorIpAddresses())
+ .append(getExpirationTimestamp(), that.getExpirationTimestamp())
+ .append(getConcatenationPartIds(), that.getConcatenationPartIds())
+ .append(getUploadConcatHeaderValue(), that.getUploadConcatHeaderValue())
+ .isEquals();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder(17, 37)
+ .append(getUploadType())
+ .append(getOffset())
+ .append(getEncodedMetadata())
+ .append(getLength())
+ .append(getId())
+ .append(getOwnerKey())
+ .append(getCreatorIpAddresses())
+ .append(getExpirationTimestamp())
+ .append(getConcatenationPartIds())
+ .append(getUploadConcatHeaderValue())
+ .toHashCode();
+ }
+
+ /** Get the current time in the number of milliseconds since January 1, 1970, 00:00:00 GMT */
+ protected long getCurrentTime() {
+ return new Date().getTime();
+ }
+
+ private String[] splitToArray(String value, String separatorRegex) {
+ if (StringUtils.isBlank(value)) {
+ return new String[0];
+ } else {
+ return StringUtils.trimToEmpty(value).split(separatorRegex);
+ }
+ }
+
+ private String decode(String encodedValue) {
+ if (encodedValue == null) {
+ return null;
+ } else {
+ return new String(Base64.decodeBase64(encodedValue), Charsets.UTF_8);
+ }
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/UploadLock.java b/src/main/java/me/desair/tus/server/upload/UploadLock.java
index e45ea06..3183bff 100644
--- a/src/main/java/me/desair/tus/server/upload/UploadLock.java
+++ b/src/main/java/me/desair/tus/server/upload/UploadLock.java
@@ -2,23 +2,22 @@
import java.io.IOException;
-/**
- * Interface that represents a lock on an upload
- */
+/** Interface that represents a lock on an upload */
public interface UploadLock extends AutoCloseable {
- /**
- * Get the upload URI of the upload that is locked by this lock
- * @return The URI of the locked upload
- */
- String getUploadUri();
+ /**
+ * Get the upload URI of the upload that is locked by this lock
+ *
+ * @return The URI of the locked upload
+ */
+ String getUploadUri();
- /**
- * Method to release the lock on an upload when done processing it. It's possible that this method is
- * called multiple times within the same request
- */
- void release();
+ /**
+ * Method to release the lock on an upload when done processing it. It's possible that this method
+ * is called multiple times within the same request
+ */
+ void release();
- @Override
- void close() throws IOException;
+ @Override
+ void close() throws IOException;
}
diff --git a/src/main/java/me/desair/tus/server/upload/UploadLockingService.java b/src/main/java/me/desair/tus/server/upload/UploadLockingService.java
index 6dc52af..4a7dd51 100644
--- a/src/main/java/me/desair/tus/server/upload/UploadLockingService.java
+++ b/src/main/java/me/desair/tus/server/upload/UploadLockingService.java
@@ -1,39 +1,43 @@
package me.desair.tus.server.upload;
import java.io.IOException;
-
import me.desair.tus.server.exception.TusException;
/**
- * Service interface that can lock a specific upload so that it cannot be modified by other requests/threads.
+ * Service interface that can lock a specific upload so that it cannot be modified by other
+ * requests/threads.
*/
public interface UploadLockingService {
- /**
- * If the given URI represents a valid upload, lock that upload for processing
- * @param requestURI The URI that potentially represents an upload
- * @return The lock on the upload, or null if not lock was applied
- * @throws TusException If the upload is already locked
- */
- UploadLock lockUploadByUri(String requestURI) throws TusException, IOException;
+ /**
+ * If the given URI represents a valid upload, lock that upload for processing
+ *
+ * @param requestURI The URI that potentially represents an upload
+ * @return The lock on the upload, or null if not lock was applied
+ * @throws TusException If the upload is already locked
+ */
+ UploadLock lockUploadByUri(String requestURI) throws TusException, IOException;
- /**
- * Clean up any stale locks that are still present
- * @throws TusException When cleaning a stale lock fails
- */
- void cleanupStaleLocks() throws IOException;
+ /**
+ * Clean up any stale locks that are still present
+ *
+ * @throws TusException When cleaning a stale lock fails
+ */
+ void cleanupStaleLocks() throws IOException;
- /**
- * Check if the upload with the given ID is currently locked
- * @param id The ID of the upload to check
- * @return True if the upload is locked, false otherwise
- */
- boolean isLocked(UploadId id);
+ /**
+ * Check if the upload with the given ID is currently locked
+ *
+ * @param id The ID of the upload to check
+ * @return True if the upload is locked, false otherwise
+ */
+ boolean isLocked(UploadId id);
- /**
- * Set an instance if IdFactory to be used for creating identities and extracting them from uploadURIs
- *
- * @param idFactory The {@link UploadIdFactory} to use within this locking service
- */
- void setIdFactory(UploadIdFactory idFactory);
+ /**
+ * Set an instance if IdFactory to be used for creating identities and extracting them from
+ * uploadURIs
+ *
+ * @param idFactory The {@link UploadIdFactory} to use within this locking service
+ */
+ void setIdFactory(UploadIdFactory idFactory);
}
diff --git a/src/main/java/me/desair/tus/server/upload/UploadStorageService.java b/src/main/java/me/desair/tus/server/upload/UploadStorageService.java
index f5d18c0..3aea929 100644
--- a/src/main/java/me/desair/tus/server/upload/UploadStorageService.java
+++ b/src/main/java/me/desair/tus/server/upload/UploadStorageService.java
@@ -3,146 +3,166 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-
import me.desair.tus.server.exception.TusException;
import me.desair.tus.server.exception.UploadNotFoundException;
import me.desair.tus.server.upload.concatenation.UploadConcatenationService;
-/**
- * Interface to a service that is able to store the (partially) uploaded files.
- */
+/** Interface to a service that is able to store the (partially) uploaded files. */
public interface UploadStorageService {
- /**
- * Method to retrieve the upload info by its upload URL
- * @param uploadUrl The URL corresponding to this upload. This parameter can be null.
- * @param ownerKey A key representing the owner of the upload
- * @return The upload info matching the given URL, or null when not found.
- */
- UploadInfo getUploadInfo(String uploadUrl, String ownerKey) throws IOException;
-
- /**
- * Method to retrieve the upload info by its ID
- * @param id The ID of the upload
- * @return The matching upload info
- * @throws IOException When the service is not able to retrieve the upload information
- */
- UploadInfo getUploadInfo(UploadId id) throws IOException;
-
- /**
- * The URI which is configured as the upload endpoint
- * @return The URI
- */
- String getUploadURI();
-
- /**
- * Append the bytes in the give {@link InputStream} to the upload with the given ID starting at the provided offset.
- * This method also updates the {@link UploadInfo} corresponding to this upload. The Upload Storage server should
- * not exceed its max upload size when writing bytes.
- * @param upload The ID of the upload
- * @param inputStream The input stream containing the bytes to append
- * @return The new {@link UploadInfo} for this upload
- */
- UploadInfo append(UploadInfo upload, InputStream inputStream) throws IOException, TusException;
-
- /**
- * Limit the maximum upload size to the given value
- * @param maxUploadSize The maximum upload limit to set
- */
- void setMaxUploadSize(Long maxUploadSize);
-
- /**
- * Get the maximum upload size configured on this storage service
- * @return The maximum upload size or zero if no maximum
- */
- long getMaxUploadSize();
-
- /**
- * Create an upload location with the given upload information
- * @param info The Upload information to use to create the new upload
- * @param ownerKey A key representing the owner of the upload
- * @return An {@link UploadInfo} object containing the information used to create the upload and its unique ID
- */
- UploadInfo create(UploadInfo info, String ownerKey) throws IOException;
-
- /**
- * Update the upload information for the provided ID.
- * @param uploadInfo The upload info object containing the ID and information to update
- */
- void update(UploadInfo uploadInfo) throws IOException, UploadNotFoundException;
-
- /**
- * Get the uploaded bytes corresponding to the given upload URL as a stream
- * @param uploadURI The URI
- * @param ownerKey The owner key of this upload
- * @return an {@link OutputStream} containing the bytes of the upload
- */
- InputStream getUploadedBytes(String uploadURI, String ownerKey)
- throws IOException, UploadNotFoundException;
-
- /**
- * Get the uploaded bytes corresponding to the given upload ID as a stream
- * @param id the ID of the upload
- * @return an {@link OutputStream} containing the bytes of the upload
- * @throws IOException When retrieving the bytes from the storage layer fails
- * @throws UploadNotFoundException When the proved id is not linked to an upload
- */
- InputStream getUploadedBytes(UploadId id) throws IOException, UploadNotFoundException;
-
- /**
- * Copy the uploaded bytes to the given output stream
- * @param info The upload of which we should copy the bytes
- * @param outputStream The output stream where we have to copy the bytes to
- */
- void copyUploadTo(UploadInfo info, OutputStream outputStream) throws UploadNotFoundException, IOException;
-
- /**
- * Clean up any upload data that is expired according to the configured expiration time
- * @param uploadLockingService An {@link UploadLockingService} that can be used to check and lock uploads
- */
- void cleanupExpiredUploads(UploadLockingService uploadLockingService) throws IOException;
-
- /**
- * Remove the given last amount of bytes from the uploaded data
- * @param uploadInfo Upload of which to remove the bytes
- * @param byteCount The number of bytes to remove at the end
- */
- void removeLastNumberOfBytes(UploadInfo uploadInfo, long byteCount) throws UploadNotFoundException, IOException;
-
- /**
- * Terminate completed and unfinished uploads allowing the Server to free up used resources.
- * @param uploadInfo The upload to terminate
- */
- void terminateUpload(UploadInfo uploadInfo) throws UploadNotFoundException, IOException;
-
- /**
- * Get the expiration period of an upload in milliseconds
- * @return The number of milliseconds before an upload expires, or null if it cannot expire
- */
- Long getUploadExpirationPeriod();
-
- /**
- * Set the expiration period after which an in-progress upload expires
- * @param uploadExpirationPeriod The period in milliseconds
- */
- void setUploadExpirationPeriod(Long uploadExpirationPeriod);
-
- /**
- * Set the {@link UploadConcatenationService} that this upload storage service should use
- * @param concatenationService The UploadConcatenationService implementation to use
- */
- void setUploadConcatenationService(UploadConcatenationService concatenationService);
-
- /**
- * Return the {@link UploadConcatenationService} implementation that this upload service is using
- * @return The UploadConcatenationService that is being used
- */
- UploadConcatenationService getUploadConcatenationService();
-
- /**
- * Set an instance if IdFactory to be used for creating identities and extracting them from uploadURIs
- *
- * @param idFactory The {@link UploadIdFactory} to use within this storage service
- */
- void setIdFactory(UploadIdFactory idFactory);
+ /**
+ * Method to retrieve the upload info by its upload URL
+ *
+ * @param uploadUrl The URL corresponding to this upload. This parameter can be null.
+ * @param ownerKey A key representing the owner of the upload
+ * @return The upload info matching the given URL, or null when not found.
+ */
+ UploadInfo getUploadInfo(String uploadUrl, String ownerKey) throws IOException;
+
+ /**
+ * Method to retrieve the upload info by its ID
+ *
+ * @param id The ID of the upload
+ * @return The matching upload info
+ * @throws IOException When the service is not able to retrieve the upload information
+ */
+ UploadInfo getUploadInfo(UploadId id) throws IOException;
+
+ /**
+ * The URI which is configured as the upload endpoint
+ *
+ * @return The URI
+ */
+ String getUploadURI();
+
+ /**
+ * Append the bytes in the give {@link InputStream} to the upload with the given ID starting at
+ * the provided offset. This method also updates the {@link UploadInfo} corresponding to this
+ * upload. The Upload Storage server should not exceed its max upload size when writing bytes.
+ *
+ * @param upload The ID of the upload
+ * @param inputStream The input stream containing the bytes to append
+ * @return The new {@link UploadInfo} for this upload
+ */
+ UploadInfo append(UploadInfo upload, InputStream inputStream) throws IOException, TusException;
+
+ /**
+ * Limit the maximum upload size to the given value
+ *
+ * @param maxUploadSize The maximum upload limit to set
+ */
+ void setMaxUploadSize(Long maxUploadSize);
+
+ /**
+ * Get the maximum upload size configured on this storage service
+ *
+ * @return The maximum upload size or zero if no maximum
+ */
+ long getMaxUploadSize();
+
+ /**
+ * Create an upload location with the given upload information
+ *
+ * @param info The Upload information to use to create the new upload
+ * @param ownerKey A key representing the owner of the upload
+ * @return An {@link UploadInfo} object containing the information used to create the upload and
+ * its unique ID
+ */
+ UploadInfo create(UploadInfo info, String ownerKey) throws IOException;
+
+ /**
+ * Update the upload information for the provided ID.
+ *
+ * @param uploadInfo The upload info object containing the ID and information to update
+ */
+ void update(UploadInfo uploadInfo) throws IOException, UploadNotFoundException;
+
+ /**
+ * Get the uploaded bytes corresponding to the given upload URL as a stream
+ *
+ * @param uploadURI The URI
+ * @param ownerKey The owner key of this upload
+ * @return an {@link OutputStream} containing the bytes of the upload
+ */
+ InputStream getUploadedBytes(String uploadURI, String ownerKey)
+ throws IOException, UploadNotFoundException;
+
+ /**
+ * Get the uploaded bytes corresponding to the given upload ID as a stream
+ *
+ * @param id the ID of the upload
+ * @return an {@link OutputStream} containing the bytes of the upload
+ * @throws IOException When retrieving the bytes from the storage layer fails
+ * @throws UploadNotFoundException When the proved id is not linked to an upload
+ */
+ InputStream getUploadedBytes(UploadId id) throws IOException, UploadNotFoundException;
+
+ /**
+ * Copy the uploaded bytes to the given output stream
+ *
+ * @param info The upload of which we should copy the bytes
+ * @param outputStream The output stream where we have to copy the bytes to
+ */
+ void copyUploadTo(UploadInfo info, OutputStream outputStream)
+ throws UploadNotFoundException, IOException;
+
+ /**
+ * Clean up any upload data that is expired according to the configured expiration time
+ *
+ * @param uploadLockingService An {@link UploadLockingService} that can be used to check and lock
+ * uploads
+ */
+ void cleanupExpiredUploads(UploadLockingService uploadLockingService) throws IOException;
+
+ /**
+ * Remove the given last amount of bytes from the uploaded data
+ *
+ * @param uploadInfo Upload of which to remove the bytes
+ * @param byteCount The number of bytes to remove at the end
+ */
+ void removeLastNumberOfBytes(UploadInfo uploadInfo, long byteCount)
+ throws UploadNotFoundException, IOException;
+
+ /**
+ * Terminate completed and unfinished uploads allowing the Server to free up used resources.
+ *
+ * @param uploadInfo The upload to terminate
+ */
+ void terminateUpload(UploadInfo uploadInfo) throws UploadNotFoundException, IOException;
+
+ /**
+ * Get the expiration period of an upload in milliseconds
+ *
+ * @return The number of milliseconds before an upload expires, or null if it cannot expire
+ */
+ Long getUploadExpirationPeriod();
+
+ /**
+ * Set the expiration period after which an in-progress upload expires
+ *
+ * @param uploadExpirationPeriod The period in milliseconds
+ */
+ void setUploadExpirationPeriod(Long uploadExpirationPeriod);
+
+ /**
+ * Set the {@link UploadConcatenationService} that this upload storage service should use
+ *
+ * @param concatenationService The UploadConcatenationService implementation to use
+ */
+ void setUploadConcatenationService(UploadConcatenationService concatenationService);
+
+ /**
+ * Return the {@link UploadConcatenationService} implementation that this upload service is using
+ *
+ * @return The UploadConcatenationService that is being used
+ */
+ UploadConcatenationService getUploadConcatenationService();
+
+ /**
+ * Set an instance if IdFactory to be used for creating identities and extracting them from
+ * uploadURIs
+ *
+ * @param idFactory The {@link UploadIdFactory} to use within this storage service
+ */
+ void setIdFactory(UploadIdFactory idFactory);
}
diff --git a/src/main/java/me/desair/tus/server/upload/UploadType.java b/src/main/java/me/desair/tus/server/upload/UploadType.java
index aa2e652..5dceeae 100644
--- a/src/main/java/me/desair/tus/server/upload/UploadType.java
+++ b/src/main/java/me/desair/tus/server/upload/UploadType.java
@@ -1,21 +1,13 @@
package me.desair.tus.server.upload;
-/**
- * Enum that lists all the possible upload types in the tus protocol
- */
+/** Enum that lists all the possible upload types in the tus protocol */
public enum UploadType {
- /**
- * REGULAR indicates a normal upload
- */
- REGULAR,
+ /** REGULAR indicates a normal upload */
+ REGULAR,
- /**
- * PARTIAL indicates an upload that is part of a concatenated upload
- */
- PARTIAL,
+ /** PARTIAL indicates an upload that is part of a concatenated upload */
+ PARTIAL,
- /**
- * CONCATENATED is the upload that combines different partial uploads
- */
- CONCATENATED
+ /** CONCATENATED is the upload that combines different partial uploads */
+ CONCATENATED
}
diff --git a/src/main/java/me/desair/tus/server/upload/cache/ThreadLocalCachedStorageAndLockingService.java b/src/main/java/me/desair/tus/server/upload/cache/ThreadLocalCachedStorageAndLockingService.java
index 3c25ffc..3190788 100644
--- a/src/main/java/me/desair/tus/server/upload/cache/ThreadLocalCachedStorageAndLockingService.java
+++ b/src/main/java/me/desair/tus/server/upload/cache/ThreadLocalCachedStorageAndLockingService.java
@@ -5,7 +5,6 @@
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.Objects;
-
import me.desair.tus.server.exception.TusException;
import me.desair.tus.server.exception.UploadNotFoundException;
import me.desair.tus.server.upload.UploadId;
@@ -17,208 +16,213 @@
import me.desair.tus.server.upload.concatenation.UploadConcatenationService;
/**
- * Combined implementation of {@link UploadStorageService} and {@link UploadLockingService}.
- * Uses both of them as delegates but allowing to reduce disk operations during a request processing
- * by caching UploadInfo in the memory.
- * UploadLockingService service is used as a delegate to cleanup cached data on releasing a lock.
+ * Combined implementation of {@link UploadStorageService} and {@link UploadLockingService}. Uses
+ * both of them as delegates but allowing to reduce disk operations during a request processing by
+ * caching UploadInfo in the memory. UploadLockingService service is used as a delegate to cleanup
+ * cached data on releasing a lock.
*/
-public class ThreadLocalCachedStorageAndLockingService implements UploadLockingService, UploadStorageService {
-
- private final ThreadLocal> uploadInfoCache = new ThreadLocal<>();
- private final UploadLockingService lockingServiceDelegate;
- private final UploadStorageService storageServiceDelegate;
- private UploadIdFactory idFactory;
-
- public ThreadLocalCachedStorageAndLockingService(UploadStorageService storageServiceDelegate,
- UploadLockingService lockingServiceDelegate) {
- if (storageServiceDelegate.getClass() == ThreadLocalCachedStorageAndLockingService.class) {
- this.storageServiceDelegate =
- ((ThreadLocalCachedStorageAndLockingService) storageServiceDelegate).storageServiceDelegate;
- } else {
- this.storageServiceDelegate = storageServiceDelegate;
- }
- if (lockingServiceDelegate.getClass() == ThreadLocalCachedStorageAndLockingService.class) {
- this.lockingServiceDelegate =
- ((ThreadLocalCachedStorageAndLockingService) lockingServiceDelegate).lockingServiceDelegate;
- } else {
- this.lockingServiceDelegate = lockingServiceDelegate;
- }
- }
-
- @Override
- public UploadInfo getUploadInfo(UploadId id) throws IOException {
- UploadInfo uploadInfo;
- WeakReference ref = uploadInfoCache.get();
- if (ref == null || (uploadInfo = ref.get()) == null || !id.equals(uploadInfo.getId())) {
- uploadInfo = storageServiceDelegate.getUploadInfo(id);
- uploadInfoCache.set(new WeakReference<>(uploadInfo));
- }
- return uploadInfo;
- }
-
- @Override
- public UploadInfo getUploadInfo(String uploadUrl, String ownerKey) throws IOException {
- UploadInfo uploadInfo = getUploadInfo(idFactory.readUploadId(uploadUrl));
- if (uploadInfo == null || !Objects.equals(uploadInfo.getOwnerKey(), ownerKey)) {
- uploadInfo = storageServiceDelegate.getUploadInfo(uploadUrl, ownerKey);
- uploadInfoCache.set(new WeakReference<>(uploadInfo));
- }
- return uploadInfo;
- }
-
- @Override
- public void update(UploadInfo uploadInfo) throws IOException, UploadNotFoundException {
- storageServiceDelegate.update(uploadInfo);
- uploadInfoCache.set(new WeakReference<>(uploadInfo));
- }
-
- @Override
- public void setIdFactory(UploadIdFactory idFactory) {
- this.idFactory = idFactory;
- this.storageServiceDelegate.setIdFactory(idFactory);
- this.lockingServiceDelegate.setIdFactory(idFactory);
- }
-
- @Override
- public String getUploadURI() {
- return storageServiceDelegate.getUploadURI();
- }
-
+public class ThreadLocalCachedStorageAndLockingService
+ implements UploadLockingService, UploadStorageService {
+
+ private final ThreadLocal> uploadInfoCache = new ThreadLocal<>();
+ private final UploadLockingService lockingServiceDelegate;
+ private final UploadStorageService storageServiceDelegate;
+ private UploadIdFactory idFactory;
+
+ public ThreadLocalCachedStorageAndLockingService(
+ UploadStorageService storageServiceDelegate, UploadLockingService lockingServiceDelegate) {
+ if (storageServiceDelegate.getClass() == ThreadLocalCachedStorageAndLockingService.class) {
+ this.storageServiceDelegate =
+ ((ThreadLocalCachedStorageAndLockingService) storageServiceDelegate)
+ .storageServiceDelegate;
+ } else {
+ this.storageServiceDelegate = storageServiceDelegate;
+ }
+ if (lockingServiceDelegate.getClass() == ThreadLocalCachedStorageAndLockingService.class) {
+ this.lockingServiceDelegate =
+ ((ThreadLocalCachedStorageAndLockingService) lockingServiceDelegate)
+ .lockingServiceDelegate;
+ } else {
+ this.lockingServiceDelegate = lockingServiceDelegate;
+ }
+ }
+
+ @Override
+ public UploadInfo getUploadInfo(UploadId id) throws IOException {
+ UploadInfo uploadInfo;
+ WeakReference ref = uploadInfoCache.get();
+ if (ref == null || (uploadInfo = ref.get()) == null || !id.equals(uploadInfo.getId())) {
+ uploadInfo = storageServiceDelegate.getUploadInfo(id);
+ uploadInfoCache.set(new WeakReference<>(uploadInfo));
+ }
+ return uploadInfo;
+ }
+
+ @Override
+ public UploadInfo getUploadInfo(String uploadUrl, String ownerKey) throws IOException {
+ UploadInfo uploadInfo = getUploadInfo(idFactory.readUploadId(uploadUrl));
+ if (uploadInfo == null || !Objects.equals(uploadInfo.getOwnerKey(), ownerKey)) {
+ uploadInfo = storageServiceDelegate.getUploadInfo(uploadUrl, ownerKey);
+ uploadInfoCache.set(new WeakReference<>(uploadInfo));
+ }
+ return uploadInfo;
+ }
+
+ @Override
+ public void update(UploadInfo uploadInfo) throws IOException, UploadNotFoundException {
+ storageServiceDelegate.update(uploadInfo);
+ uploadInfoCache.set(new WeakReference<>(uploadInfo));
+ }
+
+ @Override
+ public void setIdFactory(UploadIdFactory idFactory) {
+ this.idFactory = idFactory;
+ this.storageServiceDelegate.setIdFactory(idFactory);
+ this.lockingServiceDelegate.setIdFactory(idFactory);
+ }
+
+ @Override
+ public String getUploadURI() {
+ return storageServiceDelegate.getUploadURI();
+ }
+
+ @Override
+ public UploadInfo append(UploadInfo upload, InputStream inputStream)
+ throws IOException, TusException {
+ UploadInfo info = storageServiceDelegate.append(upload, inputStream);
+ uploadInfoCache.set(new WeakReference<>(info));
+ return info;
+ }
+
+ @Override
+ public void setMaxUploadSize(Long maxUploadSize) {
+ storageServiceDelegate.setMaxUploadSize(maxUploadSize);
+ }
+
+ @Override
+ public long getMaxUploadSize() {
+ return storageServiceDelegate.getMaxUploadSize();
+ }
+
+ @Override
+ public UploadInfo create(UploadInfo info, String ownerKey) throws IOException {
+ UploadInfo uploadInfo = storageServiceDelegate.create(info, ownerKey);
+ uploadInfoCache.set(new WeakReference<>(uploadInfo));
+ return uploadInfo;
+ }
+
+ @Override
+ public InputStream getUploadedBytes(String uploadURI, String ownerKey)
+ throws IOException, UploadNotFoundException {
+ return storageServiceDelegate.getUploadedBytes(uploadURI, ownerKey);
+ }
+
+ @Override
+ public InputStream getUploadedBytes(UploadId id) throws IOException, UploadNotFoundException {
+ return storageServiceDelegate.getUploadedBytes(id);
+ }
+
+ @Override
+ public void copyUploadTo(UploadInfo info, OutputStream outputStream)
+ throws UploadNotFoundException, IOException {
+ storageServiceDelegate.copyUploadTo(info, outputStream);
+ uploadInfoCache.set(new WeakReference<>(info));
+ }
+
+ @Override
+ public void cleanupExpiredUploads(UploadLockingService uploadLockingService) throws IOException {
+ storageServiceDelegate.cleanupExpiredUploads(uploadLockingService);
+ // Since any cached uploads was potentially removed by the storage service
+ // we clean the cache to prevent any stale state
+ cleanupCache();
+ }
+
+ @Override
+ public void removeLastNumberOfBytes(UploadInfo uploadInfo, long byteCount)
+ throws UploadNotFoundException, IOException {
+ storageServiceDelegate.removeLastNumberOfBytes(uploadInfo, byteCount);
+ uploadInfoCache.set(new WeakReference<>(uploadInfo));
+ }
+
+ @Override
+ public void terminateUpload(UploadInfo uploadInfo) throws UploadNotFoundException, IOException {
+ storageServiceDelegate.terminateUpload(uploadInfo);
+ // Since the upload is terminated and potentially removed by the storage service
+ // we clean the cache to prevent any stale state
+ cleanupCache();
+ }
+
+ @Override
+ public Long getUploadExpirationPeriod() {
+ return storageServiceDelegate.getUploadExpirationPeriod();
+ }
+
+ @Override
+ public void setUploadExpirationPeriod(Long uploadExpirationPeriod) {
+ storageServiceDelegate.setUploadExpirationPeriod(uploadExpirationPeriod);
+ }
+
+ @Override
+ public void setUploadConcatenationService(UploadConcatenationService concatenationService) {
+ storageServiceDelegate.setUploadConcatenationService(concatenationService);
+ }
+
+ @Override
+ public UploadConcatenationService getUploadConcatenationService() {
+ return storageServiceDelegate.getUploadConcatenationService();
+ }
+
+ @Override
+ public UploadLock lockUploadByUri(String requestURI) throws TusException, IOException {
+ UploadLock uploadLock = lockingServiceDelegate.lockUploadByUri(requestURI);
+ return new CachedLock(uploadLock);
+ }
+
+ @Override
+ public void cleanupStaleLocks() throws IOException {
+ lockingServiceDelegate.cleanupStaleLocks();
+ cleanupCache();
+ }
+
+ @Override
+ public boolean isLocked(UploadId id) {
+ return lockingServiceDelegate.isLocked(id);
+ }
+
+ private void cleanupCache() {
+ WeakReference ref = uploadInfoCache.get();
+ if (ref != null) {
+ uploadInfoCache.remove();
+ ref.clear();
+ }
+ }
+
+ class CachedLock implements UploadLock {
+
+ private final UploadLock delegate;
+
+ CachedLock(UploadLock delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public String getUploadUri() {
+ return delegate != null ? delegate.getUploadUri() : null;
+ }
+
@Override
- public UploadInfo append(UploadInfo upload, InputStream inputStream) throws IOException, TusException {
- UploadInfo info = storageServiceDelegate.append(upload, inputStream);
- uploadInfoCache.set(new WeakReference<>(info));
- return info;
- }
-
- @Override
- public void setMaxUploadSize(Long maxUploadSize) {
- storageServiceDelegate.setMaxUploadSize(maxUploadSize);
- }
-
- @Override
- public long getMaxUploadSize() {
- return storageServiceDelegate.getMaxUploadSize();
- }
-
- @Override
- public UploadInfo create(UploadInfo info, String ownerKey) throws IOException {
- UploadInfo uploadInfo = storageServiceDelegate.create(info, ownerKey);
- uploadInfoCache.set(new WeakReference<>(uploadInfo));
- return uploadInfo;
-
- }
-
- @Override
- public InputStream getUploadedBytes(String uploadURI, String ownerKey) throws IOException, UploadNotFoundException {
- return storageServiceDelegate.getUploadedBytes(uploadURI, ownerKey);
- }
-
- @Override
- public InputStream getUploadedBytes(UploadId id) throws IOException, UploadNotFoundException {
- return storageServiceDelegate.getUploadedBytes(id);
- }
-
- @Override
- public void copyUploadTo(UploadInfo info, OutputStream outputStream) throws UploadNotFoundException, IOException {
- storageServiceDelegate.copyUploadTo(info, outputStream);
- uploadInfoCache.set(new WeakReference<>(info));
- }
-
- @Override
- public void cleanupExpiredUploads(UploadLockingService uploadLockingService) throws IOException {
- storageServiceDelegate.cleanupExpiredUploads(uploadLockingService);
- //Since any cached uploads was potentially removed by the storage service
- //we clean the cache to prevent any stale state
- cleanupCache();
- }
-
- @Override
- public void removeLastNumberOfBytes(UploadInfo uploadInfo, long byteCount) throws UploadNotFoundException,
- IOException {
- storageServiceDelegate.removeLastNumberOfBytes(uploadInfo, byteCount);
- uploadInfoCache.set(new WeakReference<>(uploadInfo));
- }
-
- @Override
- public void terminateUpload(UploadInfo uploadInfo) throws UploadNotFoundException, IOException {
- storageServiceDelegate.terminateUpload(uploadInfo);
- //Since the upload is terminated and potentially removed by the storage service
- //we clean the cache to prevent any stale state
- cleanupCache();
- }
-
- @Override
- public Long getUploadExpirationPeriod() {
- return storageServiceDelegate.getUploadExpirationPeriod();
- }
-
- @Override
- public void setUploadExpirationPeriod(Long uploadExpirationPeriod) {
- storageServiceDelegate.setUploadExpirationPeriod(uploadExpirationPeriod);
- }
-
- @Override
- public void setUploadConcatenationService(UploadConcatenationService concatenationService) {
- storageServiceDelegate.setUploadConcatenationService(concatenationService);
- }
-
- @Override
- public UploadConcatenationService getUploadConcatenationService() {
- return storageServiceDelegate.getUploadConcatenationService();
- }
-
- @Override
- public UploadLock lockUploadByUri(String requestURI) throws TusException, IOException {
- UploadLock uploadLock = lockingServiceDelegate.lockUploadByUri(requestURI);
- return new CachedLock(uploadLock);
- }
-
- @Override
- public void cleanupStaleLocks() throws IOException {
- lockingServiceDelegate.cleanupStaleLocks();
- cleanupCache();
- }
-
- @Override
- public boolean isLocked(UploadId id) {
- return lockingServiceDelegate.isLocked(id);
- }
-
- private void cleanupCache() {
- WeakReference ref = uploadInfoCache.get();
- if (ref != null) {
- uploadInfoCache.remove();
- ref.clear();
- }
+ public void release() {
+ if (delegate != null) {
+ delegate.release();
+ }
}
- class CachedLock implements UploadLock {
-
- private final UploadLock delegate;
-
- CachedLock(UploadLock delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public String getUploadUri() {
- return delegate != null ? delegate.getUploadUri() : null;
- }
-
- @Override
- public void release() {
- if (delegate != null) {
- delegate.release();
- }
- }
-
- @Override
- public void close() throws IOException {
- if (delegate != null) {
- delegate.close();
- }
- cleanupCache();
- }
+ @Override
+ public void close() throws IOException {
+ if (delegate != null) {
+ delegate.close();
+ }
+ cleanupCache();
}
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/concatenation/UploadConcatenationService.java b/src/main/java/me/desair/tus/server/upload/concatenation/UploadConcatenationService.java
index 1373fd4..60571ab 100644
--- a/src/main/java/me/desair/tus/server/upload/concatenation/UploadConcatenationService.java
+++ b/src/main/java/me/desair/tus/server/upload/concatenation/UploadConcatenationService.java
@@ -3,42 +3,43 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
-
import me.desair.tus.server.exception.UploadNotFoundException;
import me.desair.tus.server.upload.UploadInfo;
/**
- * Interface for a service that is able to concatenate partial uploads
- * into a concatenated upload
+ * Interface for a service that is able to concatenate partial uploads into a concatenated upload
*/
public interface UploadConcatenationService {
- /**
- * Merge the given concatenated upload if all the underlying partial uploads are completed.
- * If the underlying partial uploads are still in-progress, this method does nothing. Otherwise
- * the upload information of the concatenated upload is updated.
- *
- * @param uploadInfo The concatenated upload
- * @throws IOException If merging the upload fails
- * @throws UploadNotFoundException When one of the partial uploads cannot be found
- */
- void merge(UploadInfo uploadInfo) throws IOException, UploadNotFoundException;
+ /**
+ * Merge the given concatenated upload if all the underlying partial uploads are completed. If the
+ * underlying partial uploads are still in-progress, this method does nothing. Otherwise the
+ * upload information of the concatenated upload is updated.
+ *
+ * @param uploadInfo The concatenated upload
+ * @throws IOException If merging the upload fails
+ * @throws UploadNotFoundException When one of the partial uploads cannot be found
+ */
+ void merge(UploadInfo uploadInfo) throws IOException, UploadNotFoundException;
- /**
- * Get the concatenated bytes of this concatenated upload
- * @param uploadInfo The concatenated upload
- * @return The concatenated bytes, or null if this upload is still in progress
- * @throws IOException When return the concatenated bytes fails
- * @throws UploadNotFoundException When the or one of the partial uploads cannot be found
- */
- InputStream getConcatenatedBytes(UploadInfo uploadInfo) throws IOException, UploadNotFoundException;
+ /**
+ * Get the concatenated bytes of this concatenated upload
+ *
+ * @param uploadInfo The concatenated upload
+ * @return The concatenated bytes, or null if this upload is still in progress
+ * @throws IOException When return the concatenated bytes fails
+ * @throws UploadNotFoundException When the or one of the partial uploads cannot be found
+ */
+ InputStream getConcatenatedBytes(UploadInfo uploadInfo)
+ throws IOException, UploadNotFoundException;
- /**
- * Get all underlying partial uploads associated with the given concatenated upload
- * @param info The concatenated upload
- * @return The underlying partial uploads
- * @throws IOException When retrieving the underlying partial uploads fails
- * @throws UploadNotFoundException When one of the partial uploads cannot be found
- */
- List getPartialUploads(UploadInfo info) throws IOException, UploadNotFoundException;
+ /**
+ * Get all underlying partial uploads associated with the given concatenated upload
+ *
+ * @param info The concatenated upload
+ * @return The underlying partial uploads
+ * @throws IOException When retrieving the underlying partial uploads fails
+ * @throws UploadNotFoundException When one of the partial uploads cannot be found
+ */
+ List getPartialUploads(UploadInfo info) throws IOException, UploadNotFoundException;
}
diff --git a/src/main/java/me/desair/tus/server/upload/concatenation/UploadInputStreamEnumeration.java b/src/main/java/me/desair/tus/server/upload/concatenation/UploadInputStreamEnumeration.java
index 7f35911..c78bbd6 100644
--- a/src/main/java/me/desair/tus/server/upload/concatenation/UploadInputStreamEnumeration.java
+++ b/src/main/java/me/desair/tus/server/upload/concatenation/UploadInputStreamEnumeration.java
@@ -6,7 +6,6 @@
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
-
import me.desair.tus.server.exception.UploadNotFoundException;
import me.desair.tus.server.upload.UploadInfo;
import me.desair.tus.server.upload.UploadStorageService;
@@ -18,55 +17,54 @@
*/
public class UploadInputStreamEnumeration implements Enumeration {
- private static final Logger log = LoggerFactory.getLogger(UploadInputStreamEnumeration.class);
-
- private List uploads;
- private UploadStorageService uploadStorageService;
- private Iterator uploadIterator;
- private InputStream currentInputStream = null;
+ private static final Logger log = LoggerFactory.getLogger(UploadInputStreamEnumeration.class);
- public UploadInputStreamEnumeration(List uploadList,
- UploadStorageService uploadStorageService) {
- this.uploads = new ArrayList<>(uploadList);
- this.uploadStorageService = uploadStorageService;
- this.uploadIterator = this.uploads.iterator();
- }
+ private List uploads;
+ private UploadStorageService uploadStorageService;
+ private Iterator uploadIterator;
+ private InputStream currentInputStream = null;
- @Override
- public boolean hasMoreElements() {
- if (uploadIterator != null && uploadIterator.hasNext()) {
- currentInputStream = getNextInputStream();
- } else {
- currentInputStream = null;
- }
+ public UploadInputStreamEnumeration(
+ List uploadList, UploadStorageService uploadStorageService) {
+ this.uploads = new ArrayList<>(uploadList);
+ this.uploadStorageService = uploadStorageService;
+ this.uploadIterator = this.uploads.iterator();
+ }
- //if we could not get a next upload stream, set the iterator to null
- // to make sure repeated calls give the same result
- if (currentInputStream == null) {
- uploadIterator = null;
- return false;
- } else {
- return true;
- }
+ @Override
+ public boolean hasMoreElements() {
+ if (uploadIterator != null && uploadIterator.hasNext()) {
+ currentInputStream = getNextInputStream();
+ } else {
+ currentInputStream = null;
}
- @Override
- public InputStream nextElement() {
- return currentInputStream;
+ // if we could not get a next upload stream, set the iterator to null
+ // to make sure repeated calls give the same result
+ if (currentInputStream == null) {
+ uploadIterator = null;
+ return false;
+ } else {
+ return true;
}
+ }
- private InputStream getNextInputStream() {
- InputStream is = null;
- UploadInfo info = uploadIterator.next();
- if (info != null) {
- try {
- is = uploadStorageService.getUploadedBytes(info.getId());
- } catch (IOException | UploadNotFoundException ex) {
- log.error("Error while retrieving input stream for upload with ID " + info.getId(), ex);
- is = null;
- }
- }
- return is;
- }
+ @Override
+ public InputStream nextElement() {
+ return currentInputStream;
+ }
+ private InputStream getNextInputStream() {
+ InputStream is = null;
+ UploadInfo info = uploadIterator.next();
+ if (info != null) {
+ try {
+ is = uploadStorageService.getUploadedBytes(info.getId());
+ } catch (IOException | UploadNotFoundException ex) {
+ log.error("Error while retrieving input stream for upload with ID " + info.getId(), ex);
+ is = null;
+ }
+ }
+ return is;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/concatenation/VirtualConcatenationService.java b/src/main/java/me/desair/tus/server/upload/concatenation/VirtualConcatenationService.java
index 844d9b3..3006c9e 100644
--- a/src/main/java/me/desair/tus/server/upload/concatenation/VirtualConcatenationService.java
+++ b/src/main/java/me/desair/tus/server/upload/concatenation/VirtualConcatenationService.java
@@ -6,7 +6,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-
import me.desair.tus.server.exception.UploadNotFoundException;
import me.desair.tus.server.upload.UploadInfo;
import me.desair.tus.server.upload.UploadStorageService;
@@ -14,122 +13,129 @@
import org.slf4j.LoggerFactory;
/**
- * {@link UploadConcatenationService} implementation that uses the file system to keep track
- * of concatenated uploads. The concatenation is executed "virtually" meaning that upload bytes
- * are not duplicated to the upload but "concatenated" on the fly.
+ * {@link UploadConcatenationService} implementation that uses the file system to keep track of
+ * concatenated uploads. The concatenation is executed "virtually" meaning that upload bytes are not
+ * duplicated to the upload but "concatenated" on the fly.
*/
public class VirtualConcatenationService implements UploadConcatenationService {
- private static final Logger log = LoggerFactory.getLogger(VirtualConcatenationService.class);
-
- private UploadStorageService uploadStorageService;
+ private static final Logger log = LoggerFactory.getLogger(VirtualConcatenationService.class);
- public VirtualConcatenationService(UploadStorageService uploadStorageService) {
- this.uploadStorageService = uploadStorageService;
- }
+ private UploadStorageService uploadStorageService;
- @Override
- public void merge(UploadInfo uploadInfo) throws IOException, UploadNotFoundException {
- if (uploadInfo != null && uploadInfo.isUploadInProgress()
- && uploadInfo.getConcatenationPartIds() != null) {
+ public VirtualConcatenationService(UploadStorageService uploadStorageService) {
+ this.uploadStorageService = uploadStorageService;
+ }
- Long expirationPeriod = uploadStorageService.getUploadExpirationPeriod();
+ @Override
+ public void merge(UploadInfo uploadInfo) throws IOException, UploadNotFoundException {
+ if (uploadInfo != null
+ && uploadInfo.isUploadInProgress()
+ && uploadInfo.getConcatenationPartIds() != null) {
- List partialUploads = getPartialUploads(uploadInfo);
+ Long expirationPeriod = uploadStorageService.getUploadExpirationPeriod();
- Long totalLength = calculateTotalLength(partialUploads);
- boolean completed = checkAllCompleted(expirationPeriod, partialUploads);
+ List partialUploads = getPartialUploads(uploadInfo);
- if (totalLength != null && totalLength > 0) {
- uploadInfo.setLength(totalLength);
+ Long totalLength = calculateTotalLength(partialUploads);
+ boolean completed = checkAllCompleted(expirationPeriod, partialUploads);
- if (completed) {
- uploadInfo.setOffset(totalLength);
- }
+ if (totalLength != null && totalLength > 0) {
+ uploadInfo.setLength(totalLength);
- if (expirationPeriod != null) {
- uploadInfo.updateExpiration(expirationPeriod);
- }
-
- updateUpload(uploadInfo);
- }
+ if (completed) {
+ uploadInfo.setOffset(totalLength);
}
- }
- @Override
- public InputStream getConcatenatedBytes(UploadInfo uploadInfo) throws IOException, UploadNotFoundException {
- merge(uploadInfo);
-
- if (uploadInfo == null || uploadInfo.isUploadInProgress()) {
- return null;
- } else {
- List uploads = getPartialUploads(uploadInfo);
- return new SequenceInputStream(new UploadInputStreamEnumeration(uploads, uploadStorageService));
+ if (expirationPeriod != null) {
+ uploadInfo.updateExpiration(expirationPeriod);
}
- }
- @Override
- public List getPartialUploads(UploadInfo info) throws IOException, UploadNotFoundException {
- List concatenationParts = info.getConcatenationPartIds();
-
- if (concatenationParts == null || concatenationParts.isEmpty()) {
- return Collections.emptyList();
+ updateUpload(uploadInfo);
+ }
+ }
+ }
+
+ @Override
+ public InputStream getConcatenatedBytes(UploadInfo uploadInfo)
+ throws IOException, UploadNotFoundException {
+ merge(uploadInfo);
+
+ if (uploadInfo == null || uploadInfo.isUploadInProgress()) {
+ return null;
+ } else {
+ List uploads = getPartialUploads(uploadInfo);
+ return new SequenceInputStream(
+ new UploadInputStreamEnumeration(uploads, uploadStorageService));
+ }
+ }
+
+ @Override
+ public List getPartialUploads(UploadInfo info)
+ throws IOException, UploadNotFoundException {
+ List concatenationParts = info.getConcatenationPartIds();
+
+ if (concatenationParts == null || concatenationParts.isEmpty()) {
+ return Collections.emptyList();
+ } else {
+ List output = new ArrayList<>(concatenationParts.size());
+ for (String childUri : concatenationParts) {
+ UploadInfo childInfo = uploadStorageService.getUploadInfo(childUri, info.getOwnerKey());
+ if (childInfo == null) {
+ throw new UploadNotFoundException(
+ "Upload with URI " + childUri + " was not found for owner " + info.getOwnerKey());
} else {
- List output = new ArrayList<>(concatenationParts.size());
- for (String childUri : concatenationParts) {
- UploadInfo childInfo = uploadStorageService.getUploadInfo(childUri, info.getOwnerKey());
- if (childInfo == null) {
- throw new UploadNotFoundException("Upload with URI " + childUri
- + " was not found for owner " + info.getOwnerKey());
- } else {
- output.add(childInfo);
- }
- }
- return output;
+ output.add(childInfo);
}
+ }
+ return output;
}
-
- private Long calculateTotalLength(List partialUploads) {
- Long totalLength = 0L;
-
- for (UploadInfo childInfo : partialUploads) {
- if (childInfo.getLength() == null) {
- //One of our partial uploads does not have a length, we can't calculate the total length yet
- totalLength = null;
- } else if (totalLength != null) {
- totalLength += childInfo.getLength();
- }
- }
-
- return totalLength;
+ }
+
+ private Long calculateTotalLength(List partialUploads) {
+ Long totalLength = 0L;
+
+ for (UploadInfo childInfo : partialUploads) {
+ if (childInfo.getLength() == null) {
+ // One of our partial uploads does not have a length, we can't calculate the total
+ // length
+ // yet
+ totalLength = null;
+ } else if (totalLength != null) {
+ totalLength += childInfo.getLength();
+ }
}
- private boolean checkAllCompleted(Long expirationPeriod, List partialUploads)
- throws IOException {
+ return totalLength;
+ }
- boolean completed = true;
+ private boolean checkAllCompleted(Long expirationPeriod, List partialUploads)
+ throws IOException {
- for (UploadInfo childInfo : partialUploads) {
- if (childInfo.isUploadInProgress()) {
- completed = false;
+ boolean completed = true;
- } else if (expirationPeriod != null) {
- //Make sure our child uploads do not expire
- //since the partial child upload is complete, it's safe to update it.
- childInfo.updateExpiration(expirationPeriod);
- updateUpload(childInfo);
- }
- }
+ for (UploadInfo childInfo : partialUploads) {
+ if (childInfo.isUploadInProgress()) {
+ completed = false;
- return completed;
+ } else if (expirationPeriod != null) {
+ // Make sure our child uploads do not expire
+ // since the partial child upload is complete, it's safe to update it.
+ childInfo.updateExpiration(expirationPeriod);
+ updateUpload(childInfo);
+ }
}
- private void updateUpload(UploadInfo uploadInfo) throws IOException {
- try {
- uploadStorageService.update(uploadInfo);
- } catch (UploadNotFoundException e) {
- log.warn("Unexpected exception occurred while saving upload info with ID " + uploadInfo.getId(), e);
- }
- }
+ return completed;
+ }
+ private void updateUpload(UploadInfo uploadInfo) throws IOException {
+ try {
+ uploadStorageService.update(uploadInfo);
+ } catch (UploadNotFoundException e) {
+ log.warn(
+ "Unexpected exception occurred while saving upload info with ID " + uploadInfo.getId(),
+ e);
+ }
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/disk/AbstractDiskBasedService.java b/src/main/java/me/desair/tus/server/upload/disk/AbstractDiskBasedService.java
index a9cd430..083484c 100644
--- a/src/main/java/me/desair/tus/server/upload/disk/AbstractDiskBasedService.java
+++ b/src/main/java/me/desair/tus/server/upload/disk/AbstractDiskBasedService.java
@@ -4,52 +4,50 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-
import me.desair.tus.server.TusFileUploadService;
import me.desair.tus.server.upload.UploadId;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * Common abstract super class to implement service that use the disk file system
- */
+/** Common abstract super class to implement service that use the disk file system */
public class AbstractDiskBasedService {
- private static final Logger log = LoggerFactory.getLogger(TusFileUploadService.class);
+ private static final Logger log = LoggerFactory.getLogger(TusFileUploadService.class);
- private Path storagePath;
+ private Path storagePath;
- public AbstractDiskBasedService(String path) {
- Validate.notBlank(path, "The storage path cannot be blank");
- this.storagePath = Paths.get(path);
- }
+ public AbstractDiskBasedService(String path) {
+ Validate.notBlank(path, "The storage path cannot be blank");
+ this.storagePath = Paths.get(path);
+ }
- protected Path getStoragePath() {
- return storagePath;
- }
+ protected Path getStoragePath() {
+ return storagePath;
+ }
- protected Path getPathInStorageDirectory(UploadId id) {
- if (!Files.exists(storagePath)) {
- init();
- }
-
- if (id == null) {
- return null;
- } else {
- return storagePath.resolve(id.toString());
- }
+ protected Path getPathInStorageDirectory(UploadId id) {
+ if (!Files.exists(storagePath)) {
+ init();
}
- private synchronized void init() {
- if (!Files.exists(storagePath)) {
- try {
- Files.createDirectories(storagePath);
- } catch (IOException e) {
- String message = "Unable to create the directory specified by the storage path " + storagePath;
- log.error(message, e);
- throw new StoragePathNotAvailableException(message, e);
- }
- }
+ if (id == null) {
+ return null;
+ } else {
+ return storagePath.resolve(id.toString());
+ }
+ }
+
+ private synchronized void init() {
+ if (!Files.exists(storagePath)) {
+ try {
+ Files.createDirectories(storagePath);
+ } catch (IOException e) {
+ String message =
+ "Unable to create the directory specified by the storage path " + storagePath;
+ log.error(message, e);
+ throw new StoragePathNotAvailableException(message, e);
+ }
}
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/disk/DiskLockingService.java b/src/main/java/me/desair/tus/server/upload/disk/DiskLockingService.java
index 71eafb9..8e8753d 100644
--- a/src/main/java/me/desair/tus/server/upload/disk/DiskLockingService.java
+++ b/src/main/java/me/desair/tus/server/upload/disk/DiskLockingService.java
@@ -6,7 +6,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
-
import me.desair.tus.server.exception.TusException;
import me.desair.tus.server.exception.UploadAlreadyLockedException;
import me.desair.tus.server.upload.UploadId;
@@ -17,91 +16,89 @@
/**
* {@link UploadLockingService} implementation that uses the file system for implementing locking
- *
- * File locking can also apply to shared network drives. This way the framework supports clustering as long as
- * the upload storage directory is mounted as a shared (network) drive.
- *
- * File locks are also automatically released on application (JVM) shutdown. This means the file locking is not
- * persistent and prevents cleanup and stale lock issues.
+ *
+ * File locking can also apply to shared network drives. This way the framework supports
+ * clustering as long as the upload storage directory is mounted as a shared (network) drive.
+ *
+ *
File locks are also automatically released on application (JVM) shutdown. This means the file
+ * locking is not persistent and prevents cleanup and stale lock issues.
*/
public class DiskLockingService extends AbstractDiskBasedService implements UploadLockingService {
- private static final String LOCK_SUB_DIRECTORY = "locks";
+ private static final String LOCK_SUB_DIRECTORY = "locks";
- private UploadIdFactory idFactory;
+ private UploadIdFactory idFactory;
- public DiskLockingService(String storagePath) {
- super(storagePath + File.separator + LOCK_SUB_DIRECTORY);
- }
+ public DiskLockingService(String storagePath) {
+ super(storagePath + File.separator + LOCK_SUB_DIRECTORY);
+ }
- public DiskLockingService(UploadIdFactory idFactory, String storagePath) {
- this(storagePath);
- Validate.notNull(idFactory, "The IdFactory cannot be null");
- this.idFactory = idFactory;
- }
+ public DiskLockingService(UploadIdFactory idFactory, String storagePath) {
+ this(storagePath);
+ Validate.notNull(idFactory, "The IdFactory cannot be null");
+ this.idFactory = idFactory;
+ }
- @Override
- public UploadLock lockUploadByUri(String requestURI) throws TusException, IOException {
+ @Override
+ public UploadLock lockUploadByUri(String requestURI) throws TusException, IOException {
- UploadId id = idFactory.readUploadId(requestURI);
+ UploadId id = idFactory.readUploadId(requestURI);
- UploadLock lock = null;
+ UploadLock lock = null;
- Path lockPath = getLockPath(id);
- //If lockPath is not null, we know this is a valid Upload URI
- if (lockPath != null) {
- lock = new FileBasedLock(requestURI, lockPath);
- }
- return lock;
+ Path lockPath = getLockPath(id);
+ // If lockPath is not null, we know this is a valid Upload URI
+ if (lockPath != null) {
+ lock = new FileBasedLock(requestURI, lockPath);
}
+ return lock;
+ }
- @Override
- public void cleanupStaleLocks() throws IOException {
- try (DirectoryStream locksStream = Files.newDirectoryStream(getStoragePath())) {
- for (Path path : locksStream) {
-
- FileTime lastModifiedTime = Files.getLastModifiedTime(path);
- if (lastModifiedTime.toMillis() < System.currentTimeMillis() - 10000L) {
- UploadId id = new UploadId(path.getFileName().toString());
+ @Override
+ public void cleanupStaleLocks() throws IOException {
+ try (DirectoryStream locksStream = Files.newDirectoryStream(getStoragePath())) {
+ for (Path path : locksStream) {
- if (!isLocked(id)) {
- Files.deleteIfExists(path);
- }
- }
+ FileTime lastModifiedTime = Files.getLastModifiedTime(path);
+ if (lastModifiedTime.toMillis() < System.currentTimeMillis() - 10000L) {
+ UploadId id = new UploadId(path.getFileName().toString());
- }
+ if (!isLocked(id)) {
+ Files.deleteIfExists(path);
+ }
}
+ }
}
+ }
- @Override
- public boolean isLocked(UploadId id) {
- boolean locked = false;
- Path lockPath = getLockPath(id);
+ @Override
+ public boolean isLocked(UploadId id) {
+ boolean locked = false;
+ Path lockPath = getLockPath(id);
- if (lockPath != null) {
- //Try to obtain a lock to see if the upload is currently locked
- try (UploadLock lock = new FileBasedLock(id.toString(), lockPath)) {
+ if (lockPath != null) {
+ // Try to obtain a lock to see if the upload is currently locked
+ try (UploadLock lock = new FileBasedLock(id.toString(), lockPath)) {
- //We got the lock, so it means no one else is locking it.
- locked = false;
+ // We got the lock, so it means no one else is locking it.
+ locked = false;
- } catch (UploadAlreadyLockedException | IOException e) {
- //There was already a lock
- locked = true;
- }
- }
-
- return locked;
+ } catch (UploadAlreadyLockedException | IOException e) {
+ // There was already a lock
+ locked = true;
+ }
}
- @Override
- public void setIdFactory(UploadIdFactory idFactory) {
- Validate.notNull(idFactory, "The IdFactory cannot be null");
- this.idFactory = idFactory;
- }
+ return locked;
+ }
- private Path getLockPath(UploadId id) {
- return getPathInStorageDirectory(id);
- }
+ @Override
+ public void setIdFactory(UploadIdFactory idFactory) {
+ Validate.notNull(idFactory, "The IdFactory cannot be null");
+ this.idFactory = idFactory;
+ }
+ private Path getLockPath(UploadId id) {
+ return getPathInStorageDirectory(id);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/disk/DiskStorageService.java b/src/main/java/me/desair/tus/server/upload/disk/DiskStorageService.java
index 34f5627..fb84af0 100644
--- a/src/main/java/me/desair/tus/server/upload/disk/DiskStorageService.java
+++ b/src/main/java/me/desair/tus/server/upload/disk/DiskStorageService.java
@@ -17,7 +17,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
-
import me.desair.tus.server.exception.InvalidUploadOffsetException;
import me.desair.tus.server.exception.TusException;
import me.desair.tus.server.exception.UploadNotFoundException;
@@ -35,318 +34,324 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * Implementation of {@link UploadStorageService} that implements storage on disk
- */
+/** Implementation of {@link UploadStorageService} that implements storage on disk */
public class DiskStorageService extends AbstractDiskBasedService implements UploadStorageService {
- private static final Logger log = LoggerFactory.getLogger(DiskStorageService.class);
-
- private static final String UPLOAD_SUB_DIRECTORY = "uploads";
- private static final String INFO_FILE = "info";
- private static final String DATA_FILE = "data";
-
- private Long maxUploadSize = null;
- private Long uploadExpirationPeriod = null;
- private UploadIdFactory idFactory;
- private UploadConcatenationService uploadConcatenationService;
-
- public DiskStorageService(String storagePath) {
- super(storagePath + File.separator + UPLOAD_SUB_DIRECTORY);
- setUploadConcatenationService(new VirtualConcatenationService(this));
+ private static final Logger log = LoggerFactory.getLogger(DiskStorageService.class);
+
+ private static final String UPLOAD_SUB_DIRECTORY = "uploads";
+ private static final String INFO_FILE = "info";
+ private static final String DATA_FILE = "data";
+
+ private Long maxUploadSize = null;
+ private Long uploadExpirationPeriod = null;
+ private UploadIdFactory idFactory;
+ private UploadConcatenationService uploadConcatenationService;
+
+ public DiskStorageService(String storagePath) {
+ super(storagePath + File.separator + UPLOAD_SUB_DIRECTORY);
+ setUploadConcatenationService(new VirtualConcatenationService(this));
+ }
+
+ public DiskStorageService(UploadIdFactory idFactory, String storagePath) {
+ this(storagePath);
+ Validate.notNull(idFactory, "The IdFactory cannot be null");
+ this.idFactory = idFactory;
+ }
+
+ @Override
+ public void setIdFactory(UploadIdFactory idFactory) {
+ Validate.notNull(idFactory, "The IdFactory cannot be null");
+ this.idFactory = idFactory;
+ }
+
+ @Override
+ public void setMaxUploadSize(Long maxUploadSize) {
+ this.maxUploadSize = (maxUploadSize != null && maxUploadSize > 0 ? maxUploadSize : 0);
+ }
+
+ @Override
+ public long getMaxUploadSize() {
+ return maxUploadSize == null ? 0 : maxUploadSize;
+ }
+
+ @Override
+ public UploadInfo getUploadInfo(String uploadUrl, String ownerKey) throws IOException {
+ UploadInfo uploadInfo = getUploadInfo(idFactory.readUploadId(uploadUrl));
+ if (uploadInfo == null || !Objects.equals(uploadInfo.getOwnerKey(), ownerKey)) {
+ return null;
+ } else {
+ return uploadInfo;
}
-
- public DiskStorageService(UploadIdFactory idFactory, String storagePath) {
- this(storagePath);
- Validate.notNull(idFactory, "The IdFactory cannot be null");
- this.idFactory = idFactory;
+ }
+
+ @Override
+ public UploadInfo getUploadInfo(UploadId id) throws IOException {
+ try {
+ Path infoPath = getInfoPath(id);
+ return Utils.readSerializable(infoPath, UploadInfo.class);
+ } catch (UploadNotFoundException e) {
+ return null;
}
+ }
- @Override
- public void setIdFactory(UploadIdFactory idFactory) {
- Validate.notNull(idFactory, "The IdFactory cannot be null");
- this.idFactory = idFactory;
- }
+ @Override
+ public String getUploadURI() {
+ return idFactory.getUploadURI();
+ }
- @Override
- public void setMaxUploadSize(Long maxUploadSize) {
- this.maxUploadSize = (maxUploadSize != null && maxUploadSize > 0 ? maxUploadSize : 0);
- }
+ @Override
+ public UploadInfo create(UploadInfo info, String ownerKey) throws IOException {
+ UploadId id = createNewId();
- @Override
- public long getMaxUploadSize() {
- return maxUploadSize == null ? 0 : maxUploadSize;
- }
+ createUploadDirectory(id);
- @Override
- public UploadInfo getUploadInfo(String uploadUrl, String ownerKey) throws IOException {
- UploadInfo uploadInfo = getUploadInfo(idFactory.readUploadId(uploadUrl));
- if (uploadInfo == null || !Objects.equals(uploadInfo.getOwnerKey(), ownerKey)) {
- return null;
- } else {
- return uploadInfo;
- }
- }
+ try {
+ Path bytesPath = getBytesPath(id);
- @Override
- public UploadInfo getUploadInfo(UploadId id) throws IOException {
- try {
- Path infoPath = getInfoPath(id);
- return Utils.readSerializable(infoPath, UploadInfo.class);
- } catch (UploadNotFoundException e) {
- return null;
- }
- }
+ // Create an empty file to storage the bytes of this upload
+ Files.createFile(bytesPath);
- @Override
- public String getUploadURI() {
- return idFactory.getUploadURI();
- }
+ // Set starting values
+ info.setId(id);
+ info.setOffset(0L);
+ info.setOwnerKey(ownerKey);
- @Override
- public UploadInfo create(UploadInfo info, String ownerKey) throws IOException {
- UploadId id = createNewId();
+ update(info);
- createUploadDirectory(id);
+ return info;
+ } catch (UploadNotFoundException e) {
+ // Normally this cannot happen
+ log.error("Unable to create UploadInfo because of an upload not found exception", e);
+ return null;
+ }
+ }
- try {
- Path bytesPath = getBytesPath(id);
+ @Override
+ public void update(UploadInfo uploadInfo) throws IOException, UploadNotFoundException {
+ Path infoPath = getInfoPath(uploadInfo.getId());
+ Utils.writeSerializable(uploadInfo, infoPath);
+ }
- //Create an empty file to storage the bytes of this upload
- Files.createFile(bytesPath);
+ @Override
+ public UploadInfo append(UploadInfo info, InputStream inputStream)
+ throws IOException, TusException {
+ if (info != null) {
+ Path bytesPath = getBytesPath(info.getId());
- //Set starting values
- info.setId(id);
- info.setOffset(0L);
- info.setOwnerKey(ownerKey);
+ long max = getMaxUploadSize() > 0 ? getMaxUploadSize() : Long.MAX_VALUE;
+ long transferred = 0;
+ Long offset = info.getOffset();
+ long newOffset = offset;
- update(info);
+ try (ReadableByteChannel uploadedBytes = Channels.newChannel(inputStream);
+ FileChannel file = FileChannel.open(bytesPath, WRITE)) {
- return info;
- } catch (UploadNotFoundException e) {
- //Normally this cannot happen
- log.error("Unable to create UploadInfo because of an upload not found exception", e);
- return null;
+ try {
+ // Lock will be released when the channel closes
+ file.lock();
+
+ // Validate that the given offset is at the end of the file
+ if (!offset.equals(file.size())) {
+ throw new InvalidUploadOffsetException(
+ "The upload offset does not correspond to the written"
+ + " bytes. You can only append to the end of an upload");
+ }
+
+ // write all bytes in the channel up to the configured maximum
+ transferred = file.transferFrom(uploadedBytes, offset, max - offset);
+ file.force(true);
+ newOffset = offset + transferred;
+
+ } catch (Exception ex) {
+ // An error occurred, try to write as much data as possible
+ newOffset = writeAsMuchAsPossible(file);
+ throw ex;
}
- }
- @Override
- public void update(UploadInfo uploadInfo) throws IOException, UploadNotFoundException {
- Path infoPath = getInfoPath(uploadInfo.getId());
- Utils.writeSerializable(uploadInfo, infoPath);
+ } finally {
+ info.setOffset(newOffset);
+ update(info);
+ }
}
- @Override
- public UploadInfo append(UploadInfo info, InputStream inputStream) throws IOException, TusException {
- if (info != null) {
- Path bytesPath = getBytesPath(info.getId());
-
- long max = getMaxUploadSize() > 0 ? getMaxUploadSize() : Long.MAX_VALUE;
- long transferred = 0;
- Long offset = info.getOffset();
- long newOffset = offset;
-
- try (ReadableByteChannel uploadedBytes = Channels.newChannel(inputStream);
- FileChannel file = FileChannel.open(bytesPath, WRITE)) {
-
- try {
- //Lock will be released when the channel closes
- file.lock();
-
- //Validate that the given offset is at the end of the file
- if (!offset.equals(file.size())) {
- throw new InvalidUploadOffsetException("The upload offset does not correspond to the written"
- + " bytes. You can only append to the end of an upload");
- }
-
- //write all bytes in the channel up to the configured maximum
- transferred = file.transferFrom(uploadedBytes, offset, max - offset);
- file.force(true);
- newOffset = offset + transferred;
-
- } catch (Exception ex) {
- //An error occurred, try to write as much data as possible
- newOffset = writeAsMuchAsPossible(file);
- throw ex;
- }
-
- } finally {
- info.setOffset(newOffset);
- update(info);
- }
- }
-
- return info;
- }
+ return info;
+ }
- @Override
- public void removeLastNumberOfBytes(UploadInfo info, long byteCount)
- throws UploadNotFoundException, IOException {
+ @Override
+ public void removeLastNumberOfBytes(UploadInfo info, long byteCount)
+ throws UploadNotFoundException, IOException {
- if (info != null && byteCount > 0) {
- Path bytesPath = getBytesPath(info.getId());
+ if (info != null && byteCount > 0) {
+ Path bytesPath = getBytesPath(info.getId());
- try (FileChannel file = FileChannel.open(bytesPath, WRITE)) {
+ try (FileChannel file = FileChannel.open(bytesPath, WRITE)) {
- //Lock will be released when the channel closes
- file.lock();
+ // Lock will be released when the channel closes
+ file.lock();
- file.truncate(file.size() - byteCount);
- file.force(true);
+ file.truncate(file.size() - byteCount);
+ file.force(true);
- info.setOffset(file.size());
- update(info);
- }
- }
+ info.setOffset(file.size());
+ update(info);
+ }
}
+ }
- @Override
- public void terminateUpload(UploadInfo info) throws UploadNotFoundException, IOException {
- if (info != null) {
- Path uploadPath = getPathInStorageDirectory(info.getId());
- FileUtils.deleteDirectory(uploadPath.toFile());
- }
+ @Override
+ public void terminateUpload(UploadInfo info) throws UploadNotFoundException, IOException {
+ if (info != null) {
+ Path uploadPath = getPathInStorageDirectory(info.getId());
+ FileUtils.deleteDirectory(uploadPath.toFile());
}
-
- @Override
- public Long getUploadExpirationPeriod() {
- return uploadExpirationPeriod;
+ }
+
+ @Override
+ public Long getUploadExpirationPeriod() {
+ return uploadExpirationPeriod;
+ }
+
+ @Override
+ public void setUploadExpirationPeriod(Long uploadExpirationPeriod) {
+ this.uploadExpirationPeriod = uploadExpirationPeriod;
+ }
+
+ @Override
+ public void setUploadConcatenationService(UploadConcatenationService concatenationService) {
+ Validate.notNull(concatenationService);
+ this.uploadConcatenationService = concatenationService;
+ }
+
+ @Override
+ public UploadConcatenationService getUploadConcatenationService() {
+ return uploadConcatenationService;
+ }
+
+ @Override
+ public InputStream getUploadedBytes(String uploadURI, String ownerKey)
+ throws IOException, UploadNotFoundException {
+
+ UploadId id = idFactory.readUploadId(uploadURI);
+
+ UploadInfo uploadInfo = getUploadInfo(id);
+ if (uploadInfo == null || !Objects.equals(uploadInfo.getOwnerKey(), ownerKey)) {
+ throw new UploadNotFoundException(
+ "The upload with id " + id + " could not be found for owner " + ownerKey);
+ } else {
+ return getUploadedBytes(id);
}
-
- @Override
- public void setUploadExpirationPeriod(Long uploadExpirationPeriod) {
- this.uploadExpirationPeriod = uploadExpirationPeriod;
+ }
+
+ @Override
+ public InputStream getUploadedBytes(UploadId id) throws IOException, UploadNotFoundException {
+ InputStream inputStream = null;
+ UploadInfo uploadInfo = getUploadInfo(id);
+ if (UploadType.CONCATENATED.equals(uploadInfo.getUploadType())
+ && uploadConcatenationService != null) {
+ inputStream = uploadConcatenationService.getConcatenatedBytes(uploadInfo);
+
+ } else {
+ Path bytesPath = getBytesPath(id);
+ // If bytesPath is not null, we know this is a valid Upload URI
+ if (bytesPath != null) {
+ inputStream = Channels.newInputStream(FileChannel.open(bytesPath, READ));
+ }
}
- @Override
- public void setUploadConcatenationService(UploadConcatenationService concatenationService) {
- Validate.notNull(concatenationService);
- this.uploadConcatenationService = concatenationService;
- }
+ return inputStream;
+ }
- @Override
- public UploadConcatenationService getUploadConcatenationService() {
- return uploadConcatenationService;
- }
+ @Override
+ public void copyUploadTo(UploadInfo info, OutputStream outputStream)
+ throws UploadNotFoundException, IOException {
- @Override
- public InputStream getUploadedBytes(String uploadURI, String ownerKey)
- throws IOException, UploadNotFoundException {
+ List uploads = getUploads(info);
- UploadId id = idFactory.readUploadId(uploadURI);
+ WritableByteChannel outputChannel = Channels.newChannel(outputStream);
- UploadInfo uploadInfo = getUploadInfo(id);
- if (uploadInfo == null || !Objects.equals(uploadInfo.getOwnerKey(), ownerKey)) {
- throw new UploadNotFoundException("The upload with id " + id + " could not be found for owner " + ownerKey);
- } else {
- return getUploadedBytes(id);
- }
- }
-
- @Override
- public InputStream getUploadedBytes(UploadId id) throws IOException, UploadNotFoundException {
- InputStream inputStream = null;
- UploadInfo uploadInfo = getUploadInfo(id);
- if (UploadType.CONCATENATED.equals(uploadInfo.getUploadType()) && uploadConcatenationService != null) {
- inputStream = uploadConcatenationService.getConcatenatedBytes(uploadInfo);
-
- } else {
- Path bytesPath = getBytesPath(id);
- //If bytesPath is not null, we know this is a valid Upload URI
- if (bytesPath != null) {
- inputStream = Channels.newInputStream(FileChannel.open(bytesPath, READ));
- }
- }
-
- return inputStream;
- }
-
- @Override
- public void copyUploadTo(UploadInfo info, OutputStream outputStream)
- throws UploadNotFoundException, IOException {
-
- List uploads = getUploads(info);
-
- WritableByteChannel outputChannel = Channels.newChannel(outputStream);
-
- for (UploadInfo upload : uploads) {
- if (upload == null) {
- log.warn("We cannot copy the bytes of an upload that does not exist");
-
- } else if (upload.isUploadInProgress()) {
- log.warn("We cannot copy the bytes of upload {} because it is still in progress", upload.getId());
-
- } else {
- Path bytesPath = getBytesPath(upload.getId());
- try (FileChannel file = FileChannel.open(bytesPath, READ)) {
- //Efficiently copy the bytes to the output stream
- file.transferTo(0, upload.getLength(), outputChannel);
- }
- }
- }
- }
+ for (UploadInfo upload : uploads) {
+ if (upload == null) {
+ log.warn("We cannot copy the bytes of an upload that does not exist");
- @Override
- public void cleanupExpiredUploads(UploadLockingService uploadLockingService) throws IOException {
- try (DirectoryStream expiredUploadsStream = Files.newDirectoryStream(getStoragePath(),
- new ExpiredUploadFilter(this, uploadLockingService))) {
+ } else if (upload.isUploadInProgress()) {
+ log.warn(
+ "We cannot copy the bytes of upload {} because it is still in progress",
+ upload.getId());
- for (Path path : expiredUploadsStream) {
- FileUtils.deleteDirectory(path.toFile());
- }
+ } else {
+ Path bytesPath = getBytesPath(upload.getId());
+ try (FileChannel file = FileChannel.open(bytesPath, READ)) {
+ // Efficiently copy the bytes to the output stream
+ file.transferTo(0, upload.getLength(), outputChannel);
}
+ }
}
+ }
- private List getUploads(UploadInfo info) throws IOException, UploadNotFoundException {
- List uploads;
+ @Override
+ public void cleanupExpiredUploads(UploadLockingService uploadLockingService) throws IOException {
+ try (DirectoryStream expiredUploadsStream =
+ Files.newDirectoryStream(
+ getStoragePath(), new ExpiredUploadFilter(this, uploadLockingService))) {
- if (info != null && UploadType.CONCATENATED.equals(info.getUploadType())
- && uploadConcatenationService != null) {
- uploadConcatenationService.merge(info);
- uploads = uploadConcatenationService.getPartialUploads(info);
- } else {
- uploads = Collections.singletonList(info);
- }
- return uploads;
+ for (Path path : expiredUploadsStream) {
+ FileUtils.deleteDirectory(path.toFile());
+ }
}
-
- private Path getBytesPath(UploadId id) throws UploadNotFoundException {
- return getPathInUploadDir(id, DATA_FILE);
+ }
+
+ private List getUploads(UploadInfo info) throws IOException, UploadNotFoundException {
+ List uploads;
+
+ if (info != null
+ && UploadType.CONCATENATED.equals(info.getUploadType())
+ && uploadConcatenationService != null) {
+ uploadConcatenationService.merge(info);
+ uploads = uploadConcatenationService.getPartialUploads(info);
+ } else {
+ uploads = Collections.singletonList(info);
}
-
- private Path getInfoPath(UploadId id) throws UploadNotFoundException {
- return getPathInUploadDir(id, INFO_FILE);
+ return uploads;
+ }
+
+ private Path getBytesPath(UploadId id) throws UploadNotFoundException {
+ return getPathInUploadDir(id, DATA_FILE);
+ }
+
+ private Path getInfoPath(UploadId id) throws UploadNotFoundException {
+ return getPathInUploadDir(id, INFO_FILE);
+ }
+
+ private Path createUploadDirectory(UploadId id) throws IOException {
+ return Files.createDirectories(getPathInStorageDirectory(id));
+ }
+
+ private Path getPathInUploadDir(UploadId id, String fileName) throws UploadNotFoundException {
+ // Get the upload directory
+ Path uploadDir = getPathInStorageDirectory(id);
+ if (uploadDir != null && Files.exists(uploadDir)) {
+ return uploadDir.resolve(fileName);
+ } else {
+ throw new UploadNotFoundException("The upload for id " + id + " was not found.");
}
-
- private Path createUploadDirectory(UploadId id) throws IOException {
- return Files.createDirectories(getPathInStorageDirectory(id));
- }
-
- private Path getPathInUploadDir(UploadId id, String fileName) throws UploadNotFoundException {
- //Get the upload directory
- Path uploadDir = getPathInStorageDirectory(id);
- if (uploadDir != null && Files.exists(uploadDir)) {
- return uploadDir.resolve(fileName);
- } else {
- throw new UploadNotFoundException("The upload for id " + id + " was not found.");
- }
- }
-
- private synchronized UploadId createNewId() throws IOException {
- UploadId id;
- do {
- id = idFactory.createId();
- //For extra safety, double check that this ID is not in use yet
- } while (getUploadInfo(id) != null);
- return id;
- }
-
- private long writeAsMuchAsPossible(FileChannel file) throws IOException {
- long offset = 0;
- if (file != null) {
- file.force(true);
- offset = file.size();
- }
- return offset;
+ }
+
+ private synchronized UploadId createNewId() throws IOException {
+ UploadId id;
+ do {
+ id = idFactory.createId();
+ // For extra safety, double check that this ID is not in use yet
+ } while (getUploadInfo(id) != null);
+ return id;
+ }
+
+ private long writeAsMuchAsPossible(FileChannel file) throws IOException {
+ long offset = 0;
+ if (file != null) {
+ file.force(true);
+ offset = file.size();
}
+ return offset;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/disk/ExpiredUploadFilter.java b/src/main/java/me/desair/tus/server/upload/disk/ExpiredUploadFilter.java
index f7c7536..922e4d9 100644
--- a/src/main/java/me/desair/tus/server/upload/disk/ExpiredUploadFilter.java
+++ b/src/main/java/me/desair/tus/server/upload/disk/ExpiredUploadFilter.java
@@ -4,45 +4,43 @@
import java.nio.file.DirectoryStream;
import java.nio.file.Path;
import java.util.Objects;
-
import me.desair.tus.server.upload.UploadId;
import me.desair.tus.server.upload.UploadInfo;
import me.desair.tus.server.upload.UploadLockingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * Directory stream filter that only accepts uploads that are still in progress and expired
- */
+/** Directory stream filter that only accepts uploads that are still in progress and expired */
public class ExpiredUploadFilter implements DirectoryStream.Filter {
- private static final Logger log = LoggerFactory.getLogger(ExpiredUploadFilter.class);
-
- private DiskStorageService diskStorageService;
- private UploadLockingService uploadLockingService;
+ private static final Logger log = LoggerFactory.getLogger(ExpiredUploadFilter.class);
- ExpiredUploadFilter(DiskStorageService diskStorageService, UploadLockingService uploadLockingService) {
- this.diskStorageService = diskStorageService;
- this.uploadLockingService = uploadLockingService;
- }
+ private DiskStorageService diskStorageService;
+ private UploadLockingService uploadLockingService;
- @Override
- public boolean accept(Path upload) throws IOException {
- UploadId id = null;
- try {
- id = new UploadId(upload.getFileName().toString());
- UploadInfo info = diskStorageService.getUploadInfo(id);
+ ExpiredUploadFilter(
+ DiskStorageService diskStorageService, UploadLockingService uploadLockingService) {
+ this.diskStorageService = diskStorageService;
+ this.uploadLockingService = uploadLockingService;
+ }
- if (info != null && info.isExpired() && !uploadLockingService.isLocked(id)) {
- return true;
- }
+ @Override
+ public boolean accept(Path upload) throws IOException {
+ UploadId id = null;
+ try {
+ id = new UploadId(upload.getFileName().toString());
+ UploadInfo info = diskStorageService.getUploadInfo(id);
- } catch (Exception ex) {
- if (log.isDebugEnabled()) {
- log.debug("Not able to determine state of upload " + Objects.toString(id), ex);
- }
- }
+ if (info != null && info.isExpired() && !uploadLockingService.isLocked(id)) {
+ return true;
+ }
- return false;
+ } catch (Exception ex) {
+ if (log.isDebugEnabled()) {
+ log.debug("Not able to determine state of upload " + Objects.toString(id), ex);
+ }
}
+
+ return false;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/disk/FileBasedLock.java b/src/main/java/me/desair/tus/server/upload/disk/FileBasedLock.java
index 371b875..e741b4b 100644
--- a/src/main/java/me/desair/tus/server/upload/disk/FileBasedLock.java
+++ b/src/main/java/me/desair/tus/server/upload/disk/FileBasedLock.java
@@ -9,7 +9,6 @@
import java.nio.channels.OverlappingFileLockException;
import java.nio.file.Files;
import java.nio.file.Path;
-
import me.desair.tus.server.exception.UploadAlreadyLockedException;
import me.desair.tus.server.upload.UploadLock;
import me.desair.tus.server.util.Utils;
@@ -18,81 +17,82 @@
import org.slf4j.LoggerFactory;
/**
- * Upload locking implementation using the file system file locking mechanism.
- * File locking can also apply to shared network drives. This way the framework supports clustering as long as
- * the upload storage directory is mounted as a shared (network) drive.
- *
- * File locks are also automatically released on application (JVM) shutdown. This means the file locking is not
- * persistent and prevents cleanup and stale lock issues.
+ * Upload locking implementation using the file system file locking mechanism. File locking can also
+ * apply to shared network drives. This way the framework supports clustering as long as the upload
+ * storage directory is mounted as a shared (network) drive.
+ *
+ * File locks are also automatically released on application (JVM) shutdown. This means the file
+ * locking is not persistent and prevents cleanup and stale lock issues.
*/
public class FileBasedLock implements UploadLock {
- private static final Logger log = LoggerFactory.getLogger(FileBasedLock.class);
-
- private String uploadUri;
- private FileChannel fileChannel = null;
- protected Path lockPath;
+ private static final Logger log = LoggerFactory.getLogger(FileBasedLock.class);
- public FileBasedLock(String uploadUri, Path lockPath) throws UploadAlreadyLockedException, IOException {
- Validate.notBlank(uploadUri, "The upload URI cannot be blank");
- Validate.notNull(lockPath, "The path to the lock cannot be null");
- this.uploadUri = uploadUri;
- this.lockPath = lockPath;
+ private String uploadUri;
+ private FileChannel fileChannel = null;
+ protected Path lockPath;
- tryToObtainFileLock();
- }
+ public FileBasedLock(String uploadUri, Path lockPath)
+ throws UploadAlreadyLockedException, IOException {
+ Validate.notBlank(uploadUri, "The upload URI cannot be blank");
+ Validate.notNull(lockPath, "The path to the lock cannot be null");
+ this.uploadUri = uploadUri;
+ this.lockPath = lockPath;
- private void tryToObtainFileLock() throws UploadAlreadyLockedException, IOException {
- String message = "The upload " + getUploadUri() + " is already locked";
-
- try {
- //Try to acquire a lock
- fileChannel = createFileChannel();
- FileLock fileLock = Utils.lockFileExclusively(fileChannel);
+ tryToObtainFileLock();
+ }
- //If the upload is already locked, our lock will be null
- if (fileLock == null) {
- fileChannel.close();
- throw new UploadAlreadyLockedException(message);
- }
+ private void tryToObtainFileLock() throws UploadAlreadyLockedException, IOException {
+ String message = "The upload " + getUploadUri() + " is already locked";
- } catch (OverlappingFileLockException e) {
- if (fileChannel != null) {
- try {
- fileChannel.close();
- } catch (IOException e1) {
- //Should not happen
- }
- }
- throw new UploadAlreadyLockedException(message);
- } catch (IOException e) {
- throw new IOException("Unable to create or open file required to implement file-based locking", e);
- }
- }
+ try {
+ // Try to acquire a lock
+ fileChannel = createFileChannel();
+ FileLock fileLock = Utils.lockFileExclusively(fileChannel);
- @Override
- public String getUploadUri() {
- return uploadUri;
- }
+ // If the upload is already locked, our lock will be null
+ if (fileLock == null) {
+ fileChannel.close();
+ throw new UploadAlreadyLockedException(message);
+ }
- @Override
- public void release() {
+ } catch (OverlappingFileLockException e) {
+ if (fileChannel != null) {
try {
- //Closing the channel will also release the lock
- fileChannel.close();
- Files.deleteIfExists(lockPath);
- } catch (IOException e) {
- log.warn("Unable to release file lock for URI " + getUploadUri(), e);
+ fileChannel.close();
+ } catch (IOException e1) {
+ // Should not happen
}
+ }
+ throw new UploadAlreadyLockedException(message);
+ } catch (IOException e) {
+ throw new IOException(
+ "Unable to create or open file required to implement file-based locking", e);
}
-
- @Override
- public void close() throws IOException {
- release();
+ }
+
+ @Override
+ public String getUploadUri() {
+ return uploadUri;
+ }
+
+ @Override
+ public void release() {
+ try {
+ // Closing the channel will also release the lock
+ fileChannel.close();
+ Files.deleteIfExists(lockPath);
+ } catch (IOException e) {
+ log.warn("Unable to release file lock for URI " + getUploadUri(), e);
}
+ }
- protected FileChannel createFileChannel() throws IOException {
- return FileChannel.open(lockPath, CREATE, WRITE);
- }
+ @Override
+ public void close() throws IOException {
+ release();
+ }
+ protected FileChannel createFileChannel() throws IOException {
+ return FileChannel.open(lockPath, CREATE, WRITE);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/upload/disk/StoragePathNotAvailableException.java b/src/main/java/me/desair/tus/server/upload/disk/StoragePathNotAvailableException.java
index 8e09514..23d62ca 100644
--- a/src/main/java/me/desair/tus/server/upload/disk/StoragePathNotAvailableException.java
+++ b/src/main/java/me/desair/tus/server/upload/disk/StoragePathNotAvailableException.java
@@ -1,10 +1,8 @@
package me.desair.tus.server.upload.disk;
-/**
- * Exception thrown when the disk storage path cannot be read or created.
- */
+/** Exception thrown when the disk storage path cannot be read or created. */
public class StoragePathNotAvailableException extends RuntimeException {
- public StoragePathNotAvailableException(String message, Throwable e) {
- super(message, e);
- }
+ public StoragePathNotAvailableException(String message, Throwable e) {
+ super(message, e);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/util/AbstractExtensionRequestHandler.java b/src/main/java/me/desair/tus/server/util/AbstractExtensionRequestHandler.java
index a914299..f68a588 100644
--- a/src/main/java/me/desair/tus/server/util/AbstractExtensionRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/util/AbstractExtensionRequestHandler.java
@@ -5,35 +5,37 @@
import me.desair.tus.server.upload.UploadStorageService;
import org.apache.commons.lang3.StringUtils;
-/**
- * Abstract request handler to add tus extension values to the correct header
- */
+/** Abstract request handler to add tus extension values to the correct header */
public abstract class AbstractExtensionRequestHandler extends AbstractRequestHandler {
- @Override
- public boolean supports(HttpMethod method) {
- return HttpMethod.OPTIONS.equals(method);
- }
+ @Override
+ public boolean supports(HttpMethod method) {
+ return HttpMethod.OPTIONS.equals(method);
+ }
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) {
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey) {
- StringBuilder extensionBuilder = new StringBuilder(StringUtils.trimToEmpty(
- servletResponse.getHeader(HttpHeader.TUS_EXTENSION)));
+ StringBuilder extensionBuilder =
+ new StringBuilder(
+ StringUtils.trimToEmpty(servletResponse.getHeader(HttpHeader.TUS_EXTENSION)));
- appendExtensions(extensionBuilder);
+ appendExtensions(extensionBuilder);
- servletResponse.setHeader(HttpHeader.TUS_EXTENSION, extensionBuilder.toString());
- }
+ servletResponse.setHeader(HttpHeader.TUS_EXTENSION, extensionBuilder.toString());
+ }
- protected abstract void appendExtensions(StringBuilder extensionBuilder);
+ protected abstract void appendExtensions(StringBuilder extensionBuilder);
- protected void addExtension(StringBuilder stringBuilder, String extension) {
- if (stringBuilder.length() > 0) {
- stringBuilder.append(",");
- }
- stringBuilder.append(extension);
+ protected void addExtension(StringBuilder stringBuilder, String extension) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(",");
}
+ stringBuilder.append(extension);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/util/AbstractRequestHandler.java b/src/main/java/me/desair/tus/server/util/AbstractRequestHandler.java
index 1f00075..24c02c6 100644
--- a/src/main/java/me/desair/tus/server/util/AbstractRequestHandler.java
+++ b/src/main/java/me/desair/tus/server/util/AbstractRequestHandler.java
@@ -3,13 +3,13 @@
import me.desair.tus.server.RequestHandler;
/**
- * Abstract {@link me.desair.tus.server.RequestHandler} implementation that contains the common functionality
+ * Abstract {@link me.desair.tus.server.RequestHandler} implementation that contains the common
+ * functionality
*/
public abstract class AbstractRequestHandler implements RequestHandler {
- @Override
- public boolean isErrorHandler() {
- return false;
- }
-
+ @Override
+ public boolean isErrorHandler() {
+ return false;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/util/AbstractTusExtension.java b/src/main/java/me/desair/tus/server/util/AbstractTusExtension.java
index 1d64f2b..f407037 100644
--- a/src/main/java/me/desair/tus/server/util/AbstractTusExtension.java
+++ b/src/main/java/me/desair/tus/server/util/AbstractTusExtension.java
@@ -1,10 +1,9 @@
package me.desair.tus.server.util;
+import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
-import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.RequestHandler;
import me.desair.tus.server.RequestValidator;
@@ -14,51 +13,63 @@
public abstract class AbstractTusExtension implements TusExtension {
- private List requestValidators = new LinkedList<>();
- private List requestHandlers = new LinkedList<>();
+ private List requestValidators = new LinkedList<>();
+ private List requestHandlers = new LinkedList<>();
- public AbstractTusExtension() {
- initValidators(requestValidators);
- initRequestHandlers(requestHandlers);
- }
+ public AbstractTusExtension() {
+ initValidators(requestValidators);
+ initRequestHandlers(requestHandlers);
+ }
- protected abstract void initValidators(List requestValidators);
+ protected abstract void initValidators(List requestValidators);
- protected abstract void initRequestHandlers(List requestHandlers);
+ protected abstract void initRequestHandlers(List requestHandlers);
- @Override
- public void validate(HttpMethod method, HttpServletRequest servletRequest,
- UploadStorageService uploadStorageService, String ownerKey)
- throws TusException, IOException {
+ @Override
+ public void validate(
+ HttpMethod method,
+ HttpServletRequest servletRequest,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws TusException, IOException {
- for (RequestValidator requestValidator : requestValidators) {
- if (requestValidator.supports(method)) {
- requestValidator.validate(method, servletRequest, uploadStorageService, ownerKey);
- }
- }
+ for (RequestValidator requestValidator : requestValidators) {
+ if (requestValidator.supports(method)) {
+ requestValidator.validate(method, servletRequest, uploadStorageService, ownerKey);
+ }
}
+ }
- @Override
- public void process(HttpMethod method, TusServletRequest servletRequest,
- TusServletResponse servletResponse, UploadStorageService uploadStorageService,
- String ownerKey) throws IOException, TusException {
+ @Override
+ public void process(
+ HttpMethod method,
+ TusServletRequest servletRequest,
+ TusServletResponse servletResponse,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
- for (RequestHandler requestHandler : requestHandlers) {
- if (requestHandler.supports(method)) {
- requestHandler.process(method, servletRequest, servletResponse, uploadStorageService, ownerKey);
- }
- }
+ for (RequestHandler requestHandler : requestHandlers) {
+ if (requestHandler.supports(method)) {
+ requestHandler.process(
+ method, servletRequest, servletResponse, uploadStorageService, ownerKey);
+ }
}
+ }
- @Override
- public void handleError(HttpMethod method, TusServletRequest request, TusServletResponse response,
- UploadStorageService uploadStorageService, String ownerKey)
- throws IOException, TusException {
+ @Override
+ public void handleError(
+ HttpMethod method,
+ TusServletRequest request,
+ TusServletResponse response,
+ UploadStorageService uploadStorageService,
+ String ownerKey)
+ throws IOException, TusException {
- for (RequestHandler requestHandler : requestHandlers) {
- if (requestHandler.supports(method) && requestHandler.isErrorHandler()) {
- requestHandler.process(method, request, response, uploadStorageService, ownerKey);
- }
- }
+ for (RequestHandler requestHandler : requestHandlers) {
+ if (requestHandler.supports(method) && requestHandler.isErrorHandler()) {
+ requestHandler.process(method, request, response, uploadStorageService, ownerKey);
+ }
}
+ }
}
diff --git a/src/main/java/me/desair/tus/server/util/HttpChunkedEncodingInputStream.java b/src/main/java/me/desair/tus/server/util/HttpChunkedEncodingInputStream.java
index 9ffb0c6..58c7784 100644
--- a/src/main/java/me/desair/tus/server/util/HttpChunkedEncodingInputStream.java
+++ b/src/main/java/me/desair/tus/server/util/HttpChunkedEncodingInputStream.java
@@ -8,421 +8,419 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Transparently coalesces chunks of a HTTP stream that uses Transfer-Encoding chunked.
- * This {@link InputStream} wrapper also supports collecting Trailer header values that are
- * sent at the end of the stream.
- *
- * Based on org.apache.commons.httpclient.ChunkedInputStream
+ * Transparently coalesces chunks of a HTTP stream that uses Transfer-Encoding chunked. This {@link
+ * InputStream} wrapper also supports collecting Trailer header values that are sent at the end of
+ * the stream.
+ *
+ * Based on org.apache.commons.httpclient.ChunkedInputStream
*/
public class HttpChunkedEncodingInputStream extends InputStream {
- private static final Logger log = LoggerFactory.getLogger(HttpChunkedEncodingInputStream.class);
+ private static final Logger log = LoggerFactory.getLogger(HttpChunkedEncodingInputStream.class);
- /** The input stream that we're wrapping */
- private InputStream in;
+ /** The input stream that we're wrapping */
+ private InputStream in;
- /** The current chunk size */
- private int chunkSize = 0;
+ /** The current chunk size */
+ private int chunkSize = 0;
- /** The current position within the current chunk */
- private int pos = 0;
+ /** The current position within the current chunk */
+ private int pos = 0;
- /** True if we'are at the beginning of stream */
- private boolean bof = true;
+ /** True if we'are at the beginning of stream */
+ private boolean bof = true;
- /** True if we've reached the end of stream */
- private boolean eof = false;
+ /** True if we've reached the end of stream */
+ private boolean eof = false;
- /** True if this stream is closed */
- private boolean closed = false;
+ /** True if this stream is closed */
+ private boolean closed = false;
- /** Map to store any trailer headers */
- private Map> trailerHeaders = null;
+ /** Map to store any trailer headers */
+ private Map> trailerHeaders = null;
- /**
- * Wrap the given input stream and store any trailing headers in the provided map.
- * @param in the raw input stream
- * @param trailerHeaders Map to store any trailer header values. Can be null.
- */
- public HttpChunkedEncodingInputStream(
- InputStream in, Map> trailerHeaders) {
+ /**
+ * Wrap the given input stream and store any trailing headers in the provided map.
+ *
+ * @param in the raw input stream
+ * @param trailerHeaders Map to store any trailer header values. Can be null.
+ */
+ public HttpChunkedEncodingInputStream(InputStream in, Map> trailerHeaders) {
- if (in == null) {
- throw new IllegalArgumentException("InputStream parameter may not be null");
- }
- this.in = in;
- this.trailerHeaders = trailerHeaders;
+ if (in == null) {
+ throw new IllegalArgumentException("InputStream parameter may not be null");
}
-
- /**
- * Wrap the given input stream. Do not store any trailing headers.
- *
- * @param in the raw input stream
- */
- public HttpChunkedEncodingInputStream(InputStream in) {
- this(in, null);
+ this.in = in;
+ this.trailerHeaders = trailerHeaders;
+ }
+
+ /**
+ * Wrap the given input stream. Do not store any trailing headers.
+ *
+ * @param in the raw input stream
+ */
+ public HttpChunkedEncodingInputStream(InputStream in) {
+ this(in, null);
+ }
+
+ /**
+ * Reads the next byte of data from the input stream. The value byte is returned as an int
+ *
in the range 0
to 255
.
+ *
+ * @return -1 of the end of the stream has been reached or the next data byte
+ * @throws IOException If an IO problem occurs
+ */
+ @Override
+ public int read() throws IOException {
+
+ if (closed) {
+ throw new IOException("Attempted read from closed stream.");
}
-
- /**
- * Reads the next byte of data from the input stream. The value byte is
- * returned as an int
in the range 0
to
- * 255
.
- *
- * @return -1 of the end of the stream has been reached or the next data byte
- * @throws IOException If an IO problem occurs
- */
- @Override
- public int read() throws IOException {
-
- if (closed) {
- throw new IOException("Attempted read from closed stream.");
- }
- if (eof) {
- return -1;
- }
- if (pos >= chunkSize) {
- nextChunk();
- if (eof) {
- return -1;
- }
- }
- pos++;
- return in.read();
+ if (eof) {
+ return -1;
}
-
- /**
- * Read some bytes from the stream.
- * @param b The byte array that will hold the contents from the stream.
- * @param off The offset into the byte array at which bytes will start to be placed.
- * @param len the maximum number of bytes that can be returned.
- * @return The number of bytes returned or -1 if the end of stream has been reached.
- * @see java.io.InputStream#read(byte[], int, int)
- * @throws IOException if an IO problem occurs.
- */
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
-
- if (closed) {
- throw new IOException("Attempted read from closed stream.");
- }
-
- if (eof) {
- return -1;
- }
- if (pos >= chunkSize) {
- nextChunk();
- if (eof) {
- return -1;
- }
- }
- int minLen = Math.min(len, chunkSize - pos);
- int count = in.read(b, off, minLen);
- pos += count;
- return count;
+ if (pos >= chunkSize) {
+ nextChunk();
+ if (eof) {
+ return -1;
+ }
}
-
- /**
- * Read some bytes from the stream.
- * @param b The byte array that will hold the contents from the stream.
- * @return The number of bytes returned or -1 if the end of stream has been reached.
- * @see java.io.InputStream#read(byte[])
- * @throws IOException if an IO problem occurs.
- */
- @Override
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
+ pos++;
+ return in.read();
+ }
+
+ /**
+ * Read some bytes from the stream.
+ *
+ * @param b The byte array that will hold the contents from the stream.
+ * @param off The offset into the byte array at which bytes will start to be placed.
+ * @param len the maximum number of bytes that can be returned.
+ * @return The number of bytes returned or -1 if the end of stream has been reached.
+ * @see java.io.InputStream#read(byte[], int, int)
+ * @throws IOException if an IO problem occurs.
+ */
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+
+ if (closed) {
+ throw new IOException("Attempted read from closed stream.");
}
- /**
- * Read the CRLF terminator.
- * @throws IOException If an IO error occurs.
- */
- private void readCRLF() throws IOException {
- int cr = in.read();
- int lf = in.read();
- if ((cr != '\r') || (lf != '\n')) {
- throw new IOException(
- "CRLF expected at end of chunk: " + cr + "/" + lf);
- }
+ if (eof) {
+ return -1;
}
-
- /**
- * Read the next chunk.
- * @throws IOException If an IO error occurs.
- */
- private void nextChunk() throws IOException {
- if (!bof) {
- readCRLF();
- }
- chunkSize = getChunkSize();
- if (chunkSize < 0) {
- throw new IOException("Negative chunk size");
- }
-
- bof = false;
- pos = 0;
- if (chunkSize == 0) {
- eof = true;
- parseTrailerHeaders();
- }
+ if (pos >= chunkSize) {
+ nextChunk();
+ if (eof) {
+ return -1;
+ }
}
-
- /**
- * Expects the stream to start with a chunk size in hex with optional
- * comments after a semicolon. The line must end with a CRLF: "a3; some
- * comment\r\n" Positions the stream at the start of the next line.
- *
- * @return the chunk size as integer
- *
- * @throws IOException when the chunk size could not be parsed
- */
-
- private int getChunkSize() throws IOException {
-
- String dataString = readChunkSizeInformation();
-
- int separator = dataString.indexOf(';');
- dataString = (separator > 0)
- ? dataString.substring(0, separator).trim()
- : dataString.trim();
-
- int result;
- try {
- result = Integer.parseInt(dataString.trim(), 16);
- } catch (NumberFormatException e) {
- throw new IOException("Bad chunk size: " + dataString);
- }
- return result;
+ int minLen = Math.min(len, chunkSize - pos);
+ int count = in.read(b, off, minLen);
+ pos += count;
+ return count;
+ }
+
+ /**
+ * Read some bytes from the stream.
+ *
+ * @param b The byte array that will hold the contents from the stream.
+ * @return The number of bytes returned or -1 if the end of stream has been reached.
+ * @see java.io.InputStream#read(byte[])
+ * @throws IOException if an IO problem occurs.
+ */
+ @Override
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ /**
+ * Read the CRLF terminator.
+ *
+ * @throws IOException If an IO error occurs.
+ */
+ private void readCRLF() throws IOException {
+ int cr = in.read();
+ int lf = in.read();
+ if ((cr != '\r') || (lf != '\n')) {
+ throw new IOException("CRLF expected at end of chunk: " + cr + "/" + lf);
+ }
+ }
+
+ /**
+ * Read the next chunk.
+ *
+ * @throws IOException If an IO error occurs.
+ */
+ private void nextChunk() throws IOException {
+ if (!bof) {
+ readCRLF();
+ }
+ chunkSize = getChunkSize();
+ if (chunkSize < 0) {
+ throw new IOException("Negative chunk size");
}
- private String readChunkSizeInformation() throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ bof = false;
+ pos = 0;
+ if (chunkSize == 0) {
+ eof = true;
+ parseTrailerHeaders();
+ }
+ }
+
+ /**
+ * Expects the stream to start with a chunk size in hex with optional comments after a semicolon.
+ * The line must end with a CRLF: "a3; some comment\r\n" Positions the stream at the start of the
+ * next line.
+ *
+ * @return the chunk size as integer
+ * @throws IOException when the chunk size could not be parsed
+ */
+ private int getChunkSize() throws IOException {
+
+ String dataString = readChunkSizeInformation();
+
+ int separator = dataString.indexOf(';');
+ dataString = (separator > 0) ? dataString.substring(0, separator).trim() : dataString.trim();
+
+ int result;
+ try {
+ result = Integer.parseInt(dataString.trim(), 16);
+ } catch (NumberFormatException e) {
+ throw new IOException("Bad chunk size: " + dataString);
+ }
+ return result;
+ }
+
+ private String readChunkSizeInformation() throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ ChunkSizeState state = ChunkSizeState.NORMAL;
+ while (state != ChunkSizeState.END) {
+ int b = in.read();
+ if (b == -1) {
+ throw new IOException("Chunked stream ended unexpectedly");
+ }
+ state = state.process(in, baos, b);
+ }
- ChunkSizeState state = ChunkSizeState.NORMAL;
- while (state != ChunkSizeState.END) {
- int b = in.read();
- if (b == -1) {
- throw new IOException("Chunked stream ended unexpectedly");
- }
- state = state.process(in, baos, b);
+ // parse data
+ return new String(baos.toByteArray(), Charset.forName("US-ASCII"));
+ }
+
+ /**
+ * Reads and stores the Trailer headers.
+ *
+ * @throws IOException If an IO problem occurs
+ */
+ private void parseTrailerHeaders() throws IOException {
+ if (trailerHeaders != null) {
+ List> footers = parseHeaders(in, StandardCharsets.US_ASCII);
+ for (Pair footer : footers) {
+ List values = trailerHeaders.get(footer.getKey());
+ if (values == null) {
+ values = new LinkedList<>();
+ trailerHeaders.put(footer.getKey(), values);
}
- //parse data
- return new String(baos.toByteArray(), Charset.forName("US-ASCII"));
+ values.add(footer.getValue());
+ }
}
-
- /**
- * Reads and stores the Trailer headers.
- * @throws IOException If an IO problem occurs
- */
- private void parseTrailerHeaders() throws IOException {
- if (trailerHeaders != null) {
- List> footers = parseHeaders(in, StandardCharsets.US_ASCII);
- for (Pair footer : footers) {
- List values = trailerHeaders.get(footer.getKey());
- if (values == null) {
- values = new LinkedList<>();
- trailerHeaders.put(footer.getKey(), values);
- }
-
- values.add(footer.getValue());
- }
+ }
+
+ /**
+ * Upon close, this reads the remainder of the chunked message, leaving the underlying socket at a
+ * position to start reading the next response without scanning.
+ *
+ * @throws IOException If an IO problem occurs.
+ */
+ @Override
+ public void close() throws IOException {
+ if (!closed) {
+ try {
+ if (!eof) {
+ exhaustInputStream();
}
+ } finally {
+ eof = true;
+ closed = true;
+ }
}
-
- /**
- * Upon close, this reads the remainder of the chunked message,
- * leaving the underlying socket at a position to start reading the
- * next response without scanning.
- * @throws IOException If an IO problem occurs.
- */
- @Override
- public void close() throws IOException {
- if (!closed) {
- try {
- if (!eof) {
- exhaustInputStream();
- }
- } finally {
- eof = true;
- closed = true;
- }
- }
+ }
+
+ /**
+ * Exhaust our input stream, reading until EOF has been encountered.
+ *
+ * Note that this function is intended as a non-public utility. This is a little weird, but it
+ * seemed silly to make a utility class for this one function, so instead it is just static and
+ * shared that way.
+ *
+ * @throws IOException If an IO problem occurs
+ */
+ private void exhaustInputStream() throws IOException {
+ // read and discard the remainder of the message
+ byte[] buffer = new byte[1024];
+
+ log.trace("Clearing underlying input stream, this is what was left:");
+ while (in.read(buffer) >= 0) {
+ if (log.isTraceEnabled()) {
+ log.trace(new String(buffer, StandardCharsets.UTF_8));
+ }
}
-
- /**
- * Exhaust our input stream, reading until EOF has been encountered.
- *
- *
Note that this function is intended as a non-public utility.
- * This is a little weird, but it seemed silly to make a utility
- * class for this one function, so instead it is just static and
- * shared that way.
- *
- * @throws IOException If an IO problem occurs
- */
- private void exhaustInputStream() throws IOException {
- // read and discard the remainder of the message
- byte[] buffer = new byte[1024];
-
- log.trace("Clearing underlying input stream, this is what was left:");
- while (in.read(buffer) >= 0) {
- if (log.isTraceEnabled()) {
- log.trace(new String(buffer, StandardCharsets.UTF_8));
- }
+ }
+
+ private List> parseHeaders(InputStream is, Charset charset)
+ throws IOException {
+ List> headers = new LinkedList<>();
+ String name = null;
+ StringBuilder value = null;
+ String line = readLine(is, charset);
+ while (org.apache.commons.lang3.StringUtils.isNotBlank(line)) {
+ // Parse the header name and value
+ // Check for folded headers first
+ // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2
+ // discussion on folded headers
+ if (isLwsChar(line.charAt(0))) {
+ // we have continuation folded header
+ // so append value
+ if (value != null) {
+ value.append(' ');
+ value.append(line.trim());
}
- }
+ } else {
+ // make sure we save the previous name, value pair if present
+ addHeaderValue(headers, name, value);
- private List> parseHeaders(InputStream is, Charset charset) throws IOException {
- List> headers = new LinkedList<>();
- String name = null;
- StringBuilder value = null;
- String line = readLine(is, charset);
- while (org.apache.commons.lang3.StringUtils.isNotBlank(line)) {
- // Parse the header name and value
- // Check for folded headers first
- // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2
- // discussion on folded headers
- if (isLwsChar(line.charAt(0))) {
- // we have continuation folded header
- // so append value
- if (value != null) {
- value.append(' ');
- value.append(line.trim());
- }
- } else {
- // make sure we save the previous name, value pair if present
- addHeaderValue(headers, name, value);
-
- // Otherwise we should have normal HTTP header line
- // Parse the header name and value
- int colon = line.indexOf(':');
- if (colon >= 0) {
- name = line.substring(0, colon).trim();
- value = new StringBuilder(line.substring(colon + 1).trim());
- }
- }
-
- line = readLine(is, charset);
+ // Otherwise we should have normal HTTP header line
+ // Parse the header name and value
+ int colon = line.indexOf(':');
+ if (colon >= 0) {
+ name = line.substring(0, colon).trim();
+ value = new StringBuilder(line.substring(colon + 1).trim());
}
+ }
- // make sure we save the last name,value pair if present
- addHeaderValue(headers, name, value);
-
- return headers;
+ line = readLine(is, charset);
}
- private void addHeaderValue(List> headers, String name,
- StringBuilder value) {
- if (name != null) {
- headers.add(Pair.of(name, value.toString()));
- }
- }
+ // make sure we save the last name,value pair if present
+ addHeaderValue(headers, name, value);
- private boolean isLwsChar(char c) {
- return c == ' ' || c == '\t';
+ return headers;
+ }
+
+ private void addHeaderValue(
+ List> headers, String name, StringBuilder value) {
+ if (name != null) {
+ headers.add(Pair.of(name, value.toString()));
}
+ }
- private String readLine(InputStream inputStream, Charset charset) throws IOException {
- byte[] rawdata = readRawLine(inputStream);
- if (rawdata == null || rawdata.length == 0) {
- return null;
- }
- // strip CR and LF from the end
- int len = rawdata.length;
- int offset = 0;
- if (rawdata[len - 1] == '\n') {
- offset++;
- if (len > 1 && rawdata[len - 2] == '\r') {
- offset++;
- }
- }
+ private boolean isLwsChar(char c) {
+ return c == ' ' || c == '\t';
+ }
- return new String(rawdata, 0, len - offset, charset);
+ private String readLine(InputStream inputStream, Charset charset) throws IOException {
+ byte[] rawdata = readRawLine(inputStream);
+ if (rawdata == null || rawdata.length == 0) {
+ return null;
}
-
- private byte[] readRawLine(InputStream inputStream) throws IOException {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- int ch;
- while ((ch = inputStream.read()) >= 0) {
- buf.write(ch);
- if (ch == '\n') { // be tolerant (RFC-2616 Section 19.3)
- break;
- }
- }
- return buf.toByteArray();
+ // strip CR and LF from the end
+ int len = rawdata.length;
+ int offset = 0;
+ if (rawdata[len - 1] == '\n') {
+ offset++;
+ if (len > 1 && rawdata[len - 2] == '\r') {
+ offset++;
+ }
}
- private enum ChunkSizeState {
- NORMAL {
- @Override
- public ChunkSizeState process(InputStream in, ByteArrayOutputStream baos, int b)
- throws IOException {
-
- ChunkSizeState newState;
- if (b == '\r') {
- newState = READ_CARRIAGE_RETURN;
- } else {
- if (b == '\"') {
- newState = INSIDE_QUOTED_STRING;
- } else {
- newState = NORMAL;
- }
- baos.write(b);
- }
- return newState;
- }
- },
- READ_CARRIAGE_RETURN {
- @Override
- public ChunkSizeState process(InputStream in, ByteArrayOutputStream baos, int b)
- throws IOException {
-
- if (b != '\n') {
- // this was not CRLF
- throw new IOException("Protocol violation: Unexpected"
- + " single newline character in chunk size");
- }
- return END;
- }
- },
- INSIDE_QUOTED_STRING {
- @Override
- public ChunkSizeState process(InputStream in, ByteArrayOutputStream baos, int b)
- throws IOException {
-
- ChunkSizeState newState;
- if (b == '\\') {
- int nextByte = in.read();
- if (nextByte >= 0) {
- baos.write(nextByte);
- }
- newState = INSIDE_QUOTED_STRING;
- } else {
- if (b == '\"') {
- newState = NORMAL;
- } else {
- newState = INSIDE_QUOTED_STRING;
- }
- baos.write(b);
- }
- return newState;
- }
- },
- END {
- @Override
- public ChunkSizeState process(InputStream in, ByteArrayOutputStream baos, int b)
- throws IOException {
- throw new UnsupportedOperationException("The END state cannot do any processing");
- }
- };
-
- public abstract ChunkSizeState process(InputStream in, ByteArrayOutputStream baos, int b)
- throws IOException;
+ return new String(rawdata, 0, len - offset, charset);
+ }
+
+ private byte[] readRawLine(InputStream inputStream) throws IOException {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ int ch;
+ while ((ch = inputStream.read()) >= 0) {
+ buf.write(ch);
+ if (ch == '\n') { // be tolerant (RFC-2616 Section 19.3)
+ break;
+ }
}
+ return buf.toByteArray();
+ }
+
+ private enum ChunkSizeState {
+ NORMAL {
+ @Override
+ public ChunkSizeState process(InputStream in, ByteArrayOutputStream baos, int b)
+ throws IOException {
+
+ ChunkSizeState newState;
+ if (b == '\r') {
+ newState = READ_CARRIAGE_RETURN;
+ } else {
+ if (b == '\"') {
+ newState = INSIDE_QUOTED_STRING;
+ } else {
+ newState = NORMAL;
+ }
+ baos.write(b);
+ }
+ return newState;
+ }
+ },
+ READ_CARRIAGE_RETURN {
+ @Override
+ public ChunkSizeState process(InputStream in, ByteArrayOutputStream baos, int b)
+ throws IOException {
+
+ if (b != '\n') {
+ // this was not CRLF
+ throw new IOException(
+ "Protocol violation: Unexpected" + " single newline character in chunk size");
+ }
+ return END;
+ }
+ },
+ INSIDE_QUOTED_STRING {
+ @Override
+ public ChunkSizeState process(InputStream in, ByteArrayOutputStream baos, int b)
+ throws IOException {
+
+ ChunkSizeState newState;
+ if (b == '\\') {
+ int nextByte = in.read();
+ if (nextByte >= 0) {
+ baos.write(nextByte);
+ }
+ newState = INSIDE_QUOTED_STRING;
+ } else {
+ if (b == '\"') {
+ newState = NORMAL;
+ } else {
+ newState = INSIDE_QUOTED_STRING;
+ }
+ baos.write(b);
+ }
+ return newState;
+ }
+ },
+ END {
+ @Override
+ public ChunkSizeState process(InputStream in, ByteArrayOutputStream baos, int b)
+ throws IOException {
+ throw new UnsupportedOperationException("The END state cannot do any processing");
+ }
+ };
+
+ public abstract ChunkSizeState process(InputStream in, ByteArrayOutputStream baos, int b)
+ throws IOException;
+ }
}
diff --git a/src/main/java/me/desair/tus/server/util/TusServletRequest.java b/src/main/java/me/desair/tus/server/util/TusServletRequest.java
index 463dcf7..28094e5 100644
--- a/src/main/java/me/desair/tus/server/util/TusServletRequest.java
+++ b/src/main/java/me/desair/tus/server/util/TusServletRequest.java
@@ -1,5 +1,7 @@
package me.desair.tus.server.util;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
@@ -12,9 +14,6 @@
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletRequestWrapper;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.TusExtension;
import me.desair.tus.server.checksum.ChecksumAlgorithm;
@@ -24,129 +23,132 @@
public class TusServletRequest extends HttpServletRequestWrapper {
- private CountingInputStream countingInputStream;
- private Map digestInputStreamMap = new EnumMap<>(ChecksumAlgorithm.class);
-
- private InputStream contentInputStream = null;
- private boolean isChunkedTransferDecodingEnabled = true;
-
- private Map> trailerHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
- private Set processedBySet = new TreeSet<>();
-
- /**
- * Constructs a request object wrapping the given request.
- *
- * @param request The upload request we need to wrap
- * @param isChunkedTransferDecodingEnabled Should this request wrapper decode a chunked input stream
- * @throws IllegalArgumentException if the request is null
- */
- public TusServletRequest(HttpServletRequest request, boolean isChunkedTransferDecodingEnabled) {
- super(request);
- this.isChunkedTransferDecodingEnabled = isChunkedTransferDecodingEnabled;
+ private CountingInputStream countingInputStream;
+ private Map digestInputStreamMap =
+ new EnumMap<>(ChecksumAlgorithm.class);
+
+ private InputStream contentInputStream = null;
+ private boolean isChunkedTransferDecodingEnabled = true;
+
+ private Map> trailerHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ private Set processedBySet = new TreeSet<>();
+
+ /**
+ * Constructs a request object wrapping the given request.
+ *
+ * @param request The upload request we need to wrap
+ * @param isChunkedTransferDecodingEnabled Should this request wrapper decode a chunked input
+ * stream
+ * @throws IllegalArgumentException if the request is null
+ */
+ public TusServletRequest(HttpServletRequest request, boolean isChunkedTransferDecodingEnabled) {
+ super(request);
+ this.isChunkedTransferDecodingEnabled = isChunkedTransferDecodingEnabled;
+ }
+
+ /**
+ * Constructs a request object wrapping the given request.
+ *
+ * @param request The upload request we need to wrap
+ * @throws IllegalArgumentException if the request is null
+ */
+ public TusServletRequest(HttpServletRequest request) {
+ this(request, false);
+ }
+
+ public InputStream getContentInputStream() throws IOException {
+ if (contentInputStream == null) {
+ contentInputStream = super.getInputStream();
+
+ // If we're dealing with chunked transfer encoding,
+ // abstract it so that the rest of our code doesn't need to care
+ boolean isChunked = hasChunkedTransferEncoding();
+ if (isChunked && isChunkedTransferDecodingEnabled) {
+ contentInputStream = new HttpChunkedEncodingInputStream(contentInputStream, trailerHeaders);
+ }
+
+ countingInputStream = new CountingInputStream(contentInputStream);
+ contentInputStream = countingInputStream;
+
+ ChecksumAlgorithm checksumAlgorithm =
+ ChecksumAlgorithm.forUploadChecksumHeader(getHeader(HttpHeader.UPLOAD_CHECKSUM));
+
+ List algorithms;
+
+ if (isChunked) {
+ // Since the Checksum header can still come at the end, keep track of all checksums
+ algorithms = Arrays.asList(ChecksumAlgorithm.values());
+ } else if (checksumAlgorithm != null) {
+ algorithms = Collections.singletonList(checksumAlgorithm);
+ } else {
+ algorithms = Collections.emptyList();
+ }
+
+ for (ChecksumAlgorithm algorithm : algorithms) {
+ DigestInputStream is =
+ new DigestInputStream(contentInputStream, algorithm.getMessageDigest());
+ digestInputStreamMap.put(algorithm, is);
+
+ contentInputStream = is;
+ }
}
- /**
- * Constructs a request object wrapping the given request.
- *
- * @param request The upload request we need to wrap
- * @throws IllegalArgumentException if the request is null
- */
- public TusServletRequest(HttpServletRequest request) {
- this(request, false);
+ return contentInputStream;
+ }
+
+ public long getBytesRead() {
+ return countingInputStream == null ? 0 : countingInputStream.getByteCount();
+ }
+
+ public boolean hasCalculatedChecksum() {
+ return !digestInputStreamMap.isEmpty();
+ }
+
+ public String getCalculatedChecksum(ChecksumAlgorithm algorithm) {
+ MessageDigest messageDigest = getMessageDigest(algorithm);
+ return messageDigest == null ? null : Base64.encodeBase64String(messageDigest.digest());
+ }
+
+ /**
+ * Get the set of checksum algorithms that are actively calculated within this request
+ *
+ * @return The set of active checksum algorithms
+ */
+ public Set getEnabledChecksums() {
+ return digestInputStreamMap.keySet();
+ }
+
+ @Override
+ public String getHeader(String name) {
+ String value = super.getHeader(name);
+
+ if (StringUtils.isBlank(value) && trailerHeaders.containsKey(name)) {
+ List values = trailerHeaders.get(name);
+ if (values != null && !values.isEmpty()) {
+ value = values.get(0);
+ }
}
- public InputStream getContentInputStream() throws IOException {
- if (contentInputStream == null) {
- contentInputStream = super.getInputStream();
-
- //If we're dealing with chunked transfer encoding,
- //abstract it so that the rest of our code doesn't need to care
- boolean isChunked = hasChunkedTransferEncoding();
- if (isChunked && isChunkedTransferDecodingEnabled) {
- contentInputStream = new HttpChunkedEncodingInputStream(contentInputStream, trailerHeaders);
- }
-
- countingInputStream = new CountingInputStream(contentInputStream);
- contentInputStream = countingInputStream;
-
- ChecksumAlgorithm checksumAlgorithm = ChecksumAlgorithm.forUploadChecksumHeader(
- getHeader(HttpHeader.UPLOAD_CHECKSUM));
+ return value;
+ }
- List algorithms;
+ public boolean isProcessedBy(TusExtension processor) {
+ return processedBySet.contains(processor.getName());
+ }
- if (isChunked) {
- //Since the Checksum header can still come at the end, keep track of all checksums
- algorithms = Arrays.asList(ChecksumAlgorithm.values());
- } else if (checksumAlgorithm != null) {
- algorithms = Collections.singletonList(checksumAlgorithm);
- } else {
- algorithms = Collections.emptyList();
- }
+ public void addProcessor(TusExtension processor) {
+ processedBySet.add(processor.getName());
+ }
- for (ChecksumAlgorithm algorithm : algorithms) {
- DigestInputStream is = new DigestInputStream(contentInputStream, algorithm.getMessageDigest());
- digestInputStreamMap.put(algorithm, is);
-
- contentInputStream = is;
- }
- }
-
- return contentInputStream;
- }
-
- public long getBytesRead() {
- return countingInputStream == null ? 0 : countingInputStream.getByteCount();
- }
-
- public boolean hasCalculatedChecksum() {
- return !digestInputStreamMap.isEmpty();
- }
-
- public String getCalculatedChecksum(ChecksumAlgorithm algorithm) {
- MessageDigest messageDigest = getMessageDigest(algorithm);
- return messageDigest == null ? null :
- Base64.encodeBase64String(messageDigest.digest());
- }
-
- /**
- * Get the set of checksum algorithms that are actively calculated within this request
- * @return The set of active checksum algorithms
- */
- public Set getEnabledChecksums() {
- return digestInputStreamMap.keySet();
- }
-
- @Override
- public String getHeader(String name) {
- String value = super.getHeader(name);
-
- if (StringUtils.isBlank(value) && trailerHeaders.containsKey(name)) {
- List values = trailerHeaders.get(name);
- if (values != null && !values.isEmpty()) {
- value = values.get(0);
- }
- }
-
- return value;
- }
-
- public boolean isProcessedBy(TusExtension processor) {
- return processedBySet.contains(processor.getName());
- }
-
- public void addProcessor(TusExtension processor) {
- processedBySet.add(processor.getName());
- }
-
- private boolean hasChunkedTransferEncoding() {
- return StringUtils.equalsIgnoreCase("chunked", getHeader(HttpHeader.TRANSFER_ENCODING));
- }
+ private boolean hasChunkedTransferEncoding() {
+ return StringUtils.equalsIgnoreCase("chunked", getHeader(HttpHeader.TRANSFER_ENCODING));
+ }
- private MessageDigest getMessageDigest(ChecksumAlgorithm algorithm) {
- if (digestInputStreamMap.containsKey(algorithm)) {
- return digestInputStreamMap.get(algorithm).getMessageDigest();
- } else {
- return null;
- }
+ private MessageDigest getMessageDigest(ChecksumAlgorithm algorithm) {
+ if (digestInputStreamMap.containsKey(algorithm)) {
+ return digestInputStreamMap.get(algorithm).getMessageDigest();
+ } else {
+ return null;
}
+ }
}
diff --git a/src/main/java/me/desair/tus/server/util/TusServletResponse.java b/src/main/java/me/desair/tus/server/util/TusServletResponse.java
index 14237f0..5b0239d 100644
--- a/src/main/java/me/desair/tus/server/util/TusServletResponse.java
+++ b/src/main/java/me/desair/tus/server/util/TusServletResponse.java
@@ -1,93 +1,92 @@
package me.desair.tus.server.util;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponseWrapper;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.HttpServletResponseWrapper;
-
import org.apache.commons.lang3.StringUtils;
/**
- * {@link HttpServletResponseWrapper} to capture header values set on the current {@link HttpServletResponse}
+ * {@link HttpServletResponseWrapper} to capture header values set on the current {@link
+ * HttpServletResponse}
*/
public class TusServletResponse extends HttpServletResponseWrapper {
- private Map> headers = new HashMap<>();
-
- /**
- * Constructs a response adaptor wrapping the given response.
- *
- * @param response The response that has to be wrapped
- * @throws IllegalArgumentException if the response is null
- */
- public TusServletResponse(HttpServletResponse response) {
- super(response);
+ private Map> headers = new HashMap<>();
+
+ /**
+ * Constructs a response adaptor wrapping the given response.
+ *
+ * @param response The response that has to be wrapped
+ * @throws IllegalArgumentException if the response is null
+ */
+ public TusServletResponse(HttpServletResponse response) {
+ super(response);
+ }
+
+ @Override
+ public void setDateHeader(String name, long date) {
+ super.setDateHeader(name, date);
+ overwriteHeader(name, Objects.toString(date));
+ }
+
+ @Override
+ public void addDateHeader(String name, long date) {
+ super.addDateHeader(name, date);
+ recordHeader(name, Objects.toString(date));
+ }
+
+ @Override
+ public void setHeader(String name, String value) {
+ super.setHeader(name, value);
+ overwriteHeader(name, value);
+ }
+
+ @Override
+ public void addHeader(String name, String value) {
+ super.addHeader(name, value);
+ recordHeader(name, value);
+ }
+
+ @Override
+ public void setIntHeader(String name, int value) {
+ super.setIntHeader(name, value);
+ overwriteHeader(name, Objects.toString(value));
+ }
+
+ @Override
+ public void addIntHeader(String name, int value) {
+ super.addIntHeader(name, value);
+ recordHeader(name, Objects.toString(value));
+ }
+
+ @Override
+ public String getHeader(String name) {
+ String value;
+ if (headers.containsKey(name)) {
+ value = headers.get(name).get(0);
+ } else {
+ value = super.getHeader(name);
}
-
- @Override
- public void setDateHeader(String name, long date) {
- super.setDateHeader(name, date);
- overwriteHeader(name, Objects.toString(date));
- }
-
- @Override
- public void addDateHeader(String name, long date) {
- super.addDateHeader(name, date);
- recordHeader(name, Objects.toString(date));
+ return StringUtils.trimToNull(value);
+ }
+
+ private void recordHeader(String name, String value) {
+ List values = headers.get(name);
+ if (values == null) {
+ values = new LinkedList<>();
+ headers.put(name, values);
}
- @Override
- public void setHeader(String name, String value) {
- super.setHeader(name, value);
- overwriteHeader(name, value);
- }
-
- @Override
- public void addHeader(String name, String value) {
- super.addHeader(name, value);
- recordHeader(name, value);
- }
-
- @Override
- public void setIntHeader(String name, int value) {
- super.setIntHeader(name, value);
- overwriteHeader(name, Objects.toString(value));
- }
-
- @Override
- public void addIntHeader(String name, int value) {
- super.addIntHeader(name, value);
- recordHeader(name, Objects.toString(value));
- }
-
- @Override
- public String getHeader(String name) {
- String value;
- if (headers.containsKey(name)) {
- value = headers.get(name).get(0);
- } else {
- value = super.getHeader(name);
- }
- return StringUtils.trimToNull(value);
- }
-
- private void recordHeader(String name, String value) {
- List values = headers.get(name);
- if (values == null) {
- values = new LinkedList<>();
- headers.put(name, values);
- }
-
- values.add(value);
- }
-
- private void overwriteHeader(String name, String value) {
- List values = new LinkedList<>();
- values.add(value);
- headers.put(name, values);
- }
+ values.add(value);
+ }
+ private void overwriteHeader(String name, String value) {
+ List values = new LinkedList<>();
+ values.add(value);
+ headers.put(name, values);
+ }
}
diff --git a/src/main/java/me/desair/tus/server/util/Utils.java b/src/main/java/me/desair/tus/server/util/Utils.java
index 252915a..4423d6c 100644
--- a/src/main/java/me/desair/tus/server/util/Utils.java
+++ b/src/main/java/me/desair/tus/server/util/Utils.java
@@ -5,6 +5,7 @@
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
import static java.nio.file.StandardOpenOption.WRITE;
+import jakarta.servlet.http.HttpServletRequest;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -18,139 +19,135 @@
import java.nio.file.Path;
import java.util.LinkedList;
import java.util.List;
-import jakarta.servlet.http.HttpServletRequest;
-
import me.desair.tus.server.HttpHeader;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * Utility class that contains various static helper methods
- */
+/** Utility class that contains various static helper methods */
public class Utils {
- private static final Logger log = LoggerFactory.getLogger(Utils.class);
- private static final int LOCK_FILE_RETRY_COUNT = 3;
- private static final long LOCK_FILE_SLEEP_TIME = 500;
+ private static final Logger log = LoggerFactory.getLogger(Utils.class);
+ private static final int LOCK_FILE_RETRY_COUNT = 3;
+ private static final long LOCK_FILE_SLEEP_TIME = 500;
- private Utils() {
- //This is a utility class that only holds static utility methods
- }
+ private Utils() {
+ // This is a utility class that only holds static utility methods
+ }
- public static String getHeader(HttpServletRequest request, String header) {
- return StringUtils.trimToEmpty(request.getHeader(header));
- }
+ public static String getHeader(HttpServletRequest request, String header) {
+ return StringUtils.trimToEmpty(request.getHeader(header));
+ }
- public static Long getLongHeader(HttpServletRequest request, String header) {
- try {
- return Long.valueOf(getHeader(request, header));
- } catch (NumberFormatException ex) {
- return null;
- }
+ public static Long getLongHeader(HttpServletRequest request, String header) {
+ try {
+ return Long.valueOf(getHeader(request, header));
+ } catch (NumberFormatException ex) {
+ return null;
}
-
- /**
- * Build a comma-separated list based on the remote address of the request and the
- * X-Forwareded-For header. The list is constructed as "client, proxy1, proxy2".
- * @return A comma-separated list of ip-addresses
- */
- public static String buildRemoteIpList(HttpServletRequest servletRequest) {
- String ipAddresses = servletRequest.getRemoteAddr();
- String xforwardedForHeader = getHeader(servletRequest, HttpHeader.X_FORWARDED_FOR);
- if (xforwardedForHeader.length() > 0) {
- ipAddresses = xforwardedForHeader + ", " + ipAddresses;
- }
- return ipAddresses;
+ }
+
+ /**
+ * Build a comma-separated list based on the remote address of the request and the
+ * X-Forwareded-For header. The list is constructed as "client, proxy1, proxy2".
+ *
+ * @return A comma-separated list of ip-addresses
+ */
+ public static String buildRemoteIpList(HttpServletRequest servletRequest) {
+ String ipAddresses = servletRequest.getRemoteAddr();
+ String xforwardedForHeader = getHeader(servletRequest, HttpHeader.X_FORWARDED_FOR);
+ if (xforwardedForHeader.length() > 0) {
+ ipAddresses = xforwardedForHeader + ", " + ipAddresses;
}
+ return ipAddresses;
+ }
- public static List parseConcatenationIDsFromHeader(String uploadConcatValue) {
- List output = new LinkedList<>();
+ public static List parseConcatenationIDsFromHeader(String uploadConcatValue) {
+ List output = new LinkedList<>();
- String idString = StringUtils.substringAfter(uploadConcatValue, ";");
- for (String id : StringUtils.trimToEmpty(idString).split("\\s")) {
- output.add(id);
- }
-
- return output;
+ String idString = StringUtils.substringAfter(uploadConcatValue, ";");
+ for (String id : StringUtils.trimToEmpty(idString).split("\\s")) {
+ output.add(id);
}
- public static T readSerializable(Path path, Class clazz) throws IOException {
- T info = null;
- if (path != null) {
- try (FileChannel channel = FileChannel.open(path, READ)) {
- //Lock will be released when the channel is closed
- if (lockFileShared(channel) != null) {
-
- try (ObjectInputStream ois = new ObjectInputStream(Channels.newInputStream(channel))) {
- info = clazz.cast(ois.readObject());
- } catch (ClassNotFoundException e) {
- //This should not happen
- info = null;
- }
- } else {
- throw new IOException("Unable to lock file " + path);
- }
- }
+ return output;
+ }
+
+ public static T readSerializable(Path path, Class clazz) throws IOException {
+ T info = null;
+ if (path != null) {
+ try (FileChannel channel = FileChannel.open(path, READ)) {
+ // Lock will be released when the channel is closed
+ if (lockFileShared(channel) != null) {
+
+ try (ObjectInputStream ois = new ObjectInputStream(Channels.newInputStream(channel))) {
+ info = clazz.cast(ois.readObject());
+ } catch (ClassNotFoundException e) {
+ // This should not happen
+ info = null;
+ }
+ } else {
+ throw new IOException("Unable to lock file " + path);
}
- return info;
+ }
}
-
-
- public static void writeSerializable(Serializable object, Path path) throws IOException {
- if (path != null) {
- try (FileChannel channel = FileChannel.open(path, WRITE, CREATE, TRUNCATE_EXISTING)) {
- //Lock will be released when the channel is closed
- if (lockFileExclusively(channel) != null) {
-
- try (OutputStream buffer = new BufferedOutputStream(Channels.newOutputStream(channel));
- ObjectOutput output = new ObjectOutputStream(buffer)) {
-
- output.writeObject(object);
- }
- } else {
- throw new IOException("Unable to lock file " + path);
- }
- }
+ return info;
+ }
+
+ public static void writeSerializable(Serializable object, Path path) throws IOException {
+ if (path != null) {
+ try (FileChannel channel = FileChannel.open(path, WRITE, CREATE, TRUNCATE_EXISTING)) {
+ // Lock will be released when the channel is closed
+ if (lockFileExclusively(channel) != null) {
+
+ try (OutputStream buffer = new BufferedOutputStream(Channels.newOutputStream(channel));
+ ObjectOutput output = new ObjectOutputStream(buffer)) {
+
+ output.writeObject(object);
+ }
+ } else {
+ throw new IOException("Unable to lock file " + path);
}
+ }
}
-
- public static FileLock lockFileExclusively(FileChannel channel) throws IOException {
- return lockFile(channel, false);
+ }
+
+ public static FileLock lockFileExclusively(FileChannel channel) throws IOException {
+ return lockFile(channel, false);
+ }
+
+ public static FileLock lockFileShared(FileChannel channel) throws IOException {
+ return lockFile(channel, true);
+ }
+
+ /**
+ * Sleep the specified number of milliseconds
+ *
+ * @param sleepTimeMillis The time to sleep in milliseconds
+ */
+ public static void sleep(long sleepTimeMillis) {
+ try {
+ Thread.sleep(sleepTimeMillis);
+ } catch (InterruptedException e) {
+ log.warn("Sleep was interrupted");
+ // Restore interrupted state...
+ Thread.currentThread().interrupt();
}
+ }
- public static FileLock lockFileShared(FileChannel channel) throws IOException {
- return lockFile(channel, true);
- }
+ private static FileLock lockFile(FileChannel channel, boolean shared) throws IOException {
+ int i = 0;
+ FileLock lock = null;
+ do {
+ if (i > 0) {
+ sleep(LOCK_FILE_SLEEP_TIME);
+ }
- /**
- * Sleep the specified number of milliseconds
- * @param sleepTimeMillis The time to sleep in milliseconds
- */
- public static void sleep(long sleepTimeMillis) {
- try {
- Thread.sleep(sleepTimeMillis);
- } catch (InterruptedException e) {
- log.warn("Sleep was interrupted");
- // Restore interrupted state...
- Thread.currentThread().interrupt();
- }
- }
-
- private static FileLock lockFile(FileChannel channel, boolean shared) throws IOException {
- int i = 0;
- FileLock lock = null;
- do {
- if (i > 0) {
- sleep(LOCK_FILE_SLEEP_TIME);
- }
-
- lock = channel.tryLock(0L, Long.MAX_VALUE, shared);
+ lock = channel.tryLock(0L, Long.MAX_VALUE, shared);
- i++;
- } while (lock == null && i < LOCK_FILE_RETRY_COUNT);
-
- return lock;
- }
+ i++;
+ } while (lock == null && i < LOCK_FILE_RETRY_COUNT);
+ return lock;
+ }
}
diff --git a/src/test/java/me/desair/tus/server/AbstractTusExtensionIntegrationTest.java b/src/test/java/me/desair/tus/server/AbstractTusExtensionIntegrationTest.java
index 5b529a8..59be21b 100644
--- a/src/test/java/me/desair/tus/server/AbstractTusExtensionIntegrationTest.java
+++ b/src/test/java/me/desair/tus/server/AbstractTusExtensionIntegrationTest.java
@@ -12,7 +12,6 @@
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
-
import me.desair.tus.server.exception.TusException;
import me.desair.tus.server.upload.UploadInfo;
import me.desair.tus.server.upload.UploadStorageService;
@@ -31,76 +30,82 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public abstract class AbstractTusExtensionIntegrationTest {
- private static final Logger log = LoggerFactory.getLogger(AbstractTusExtensionIntegrationTest.class);
-
- protected AbstractTusExtension tusFeature;
-
- protected MockHttpServletRequest servletRequest;
-
- protected MockHttpServletResponse servletResponse;
-
- @Mock
- protected UploadStorageService uploadStorageService;
-
- protected UploadInfo uploadInfo;
-
- protected void prepareUploadInfo(Long offset, Long length) throws IOException, TusException {
- uploadInfo = new UploadInfo();
- uploadInfo.setOffset(offset);
- uploadInfo.setLength(length);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(uploadInfo);
- when(uploadStorageService.append(any(UploadInfo.class), any(InputStream.class))).thenReturn(uploadInfo);
- }
-
- protected void setRequestHeaders(String... headers) {
- if (headers != null && headers.length > 0) {
- for (String header : headers) {
- switch (header) {
- case HttpHeader.TUS_RESUMABLE:
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- break;
- case HttpHeader.CONTENT_TYPE:
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- break;
- case HttpHeader.UPLOAD_OFFSET:
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, uploadInfo.getOffset());
- break;
- case HttpHeader.CONTENT_LENGTH:
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH,
- uploadInfo.getLength() - uploadInfo.getOffset());
- break;
- default:
- log.warn("Undefined HTTP header " + header);
- break;
- }
- }
+ private static final Logger log =
+ LoggerFactory.getLogger(AbstractTusExtensionIntegrationTest.class);
+
+ protected AbstractTusExtension tusFeature;
+
+ protected MockHttpServletRequest servletRequest;
+
+ protected MockHttpServletResponse servletResponse;
+
+ @Mock protected UploadStorageService uploadStorageService;
+
+ protected UploadInfo uploadInfo;
+
+ protected void prepareUploadInfo(Long offset, Long length) throws IOException, TusException {
+ uploadInfo = new UploadInfo();
+ uploadInfo.setOffset(offset);
+ uploadInfo.setLength(length);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(uploadInfo);
+ when(uploadStorageService.append(any(UploadInfo.class), any(InputStream.class)))
+ .thenReturn(uploadInfo);
+ }
+
+ protected void setRequestHeaders(String... headers) {
+ if (headers != null && headers.length > 0) {
+ for (String header : headers) {
+ switch (header) {
+ case HttpHeader.TUS_RESUMABLE:
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ break;
+ case HttpHeader.CONTENT_TYPE:
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ break;
+ case HttpHeader.UPLOAD_OFFSET:
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, uploadInfo.getOffset());
+ break;
+ case HttpHeader.CONTENT_LENGTH:
+ servletRequest.addHeader(
+ HttpHeader.CONTENT_LENGTH, uploadInfo.getLength() - uploadInfo.getOffset());
+ break;
+ default:
+ log.warn("Undefined HTTP header " + header);
+ break;
}
+ }
}
+ }
- protected void executeCall(HttpMethod method, boolean readContent) throws TusException, IOException {
- tusFeature.validate(method, servletRequest, uploadStorageService, null);
- TusServletRequest tusServletRequest = new TusServletRequest(this.servletRequest, true);
-
- if (readContent) {
- StringWriter writer = new StringWriter();
- IOUtils.copy(tusServletRequest.getContentInputStream(), writer, StandardCharsets.UTF_8);
- }
-
- tusFeature.process(method, tusServletRequest,
- new TusServletResponse(servletResponse), uploadStorageService, null);
- }
-
- protected void assertResponseHeader(String header, String value) {
- assertThat(servletResponse.getHeader(header), is(value));
- }
-
- protected void assertResponseHeader(String header, String... values) {
- assertThat(Arrays.asList(servletResponse.getHeader(header).split(",")),
- containsInAnyOrder(values));
- }
+ protected void executeCall(HttpMethod method, boolean readContent)
+ throws TusException, IOException {
+ tusFeature.validate(method, servletRequest, uploadStorageService, null);
+ TusServletRequest tusServletRequest = new TusServletRequest(this.servletRequest, true);
- protected void assertResponseStatus(int httpStatus) {
- assertThat(servletResponse.getStatus(), is(httpStatus));
+ if (readContent) {
+ StringWriter writer = new StringWriter();
+ IOUtils.copy(tusServletRequest.getContentInputStream(), writer, StandardCharsets.UTF_8);
}
+ tusFeature.process(
+ method,
+ tusServletRequest,
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+ }
+
+ protected void assertResponseHeader(String header, String value) {
+ assertThat(servletResponse.getHeader(header), is(value));
+ }
+
+ protected void assertResponseHeader(String header, String... values) {
+ assertThat(
+ Arrays.asList(servletResponse.getHeader(header).split(",")), containsInAnyOrder(values));
+ }
+
+ protected void assertResponseStatus(int httpStatus) {
+ assertThat(servletResponse.getStatus(), is(httpStatus));
+ }
}
diff --git a/src/test/java/me/desair/tus/server/HttpMethodTest.java b/src/test/java/me/desair/tus/server/HttpMethodTest.java
index a85fb65..c50db1b 100644
--- a/src/test/java/me/desair/tus/server/HttpMethodTest.java
+++ b/src/test/java/me/desair/tus/server/HttpMethodTest.java
@@ -3,73 +3,75 @@
import static org.junit.Assert.assertEquals;
import java.util.EnumSet;
-
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
public class HttpMethodTest {
- @Test
- public void forName() throws Exception {
- assertEquals(HttpMethod.DELETE, HttpMethod.forName("delete"));
- assertEquals(HttpMethod.GET, HttpMethod.forName("get"));
- assertEquals(HttpMethod.HEAD, HttpMethod.forName("head"));
- assertEquals(HttpMethod.PATCH, HttpMethod.forName("patch"));
- assertEquals(HttpMethod.POST, HttpMethod.forName("post"));
- assertEquals(HttpMethod.PUT, HttpMethod.forName("put"));
- assertEquals(HttpMethod.OPTIONS, HttpMethod.forName("options"));
- assertEquals(null, HttpMethod.forName("test"));
- }
-
- @Test
- public void getMethodNormal() throws Exception {
- MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- servletRequest.setMethod("patch");
-
- assertEquals(HttpMethod.PATCH,
- HttpMethod.getMethodIfSupported(servletRequest, EnumSet.allOf(HttpMethod.class)));
- }
-
- @Test
- public void getMethodOverridden() throws Exception {
- MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- servletRequest.setMethod("post");
- servletRequest.addHeader(HttpHeader.METHOD_OVERRIDE, "patch");
-
- assertEquals(HttpMethod.PATCH,
- HttpMethod.getMethodIfSupported(servletRequest, EnumSet.allOf(HttpMethod.class)));
- }
-
- @Test
- public void getMethodOverriddenDoesNotExist() throws Exception {
- MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- servletRequest.setMethod("post");
- servletRequest.addHeader(HttpHeader.METHOD_OVERRIDE, "test");
-
- assertEquals(HttpMethod.POST,
- HttpMethod.getMethodIfSupported(servletRequest, EnumSet.allOf(HttpMethod.class)));
- }
-
- @Test(expected = NullPointerException.class)
- public void getMethodNull() throws Exception {
- HttpMethod.getMethodIfSupported(null, EnumSet.allOf(HttpMethod.class));
- }
-
- @Test
- public void getMethodNotSupported() throws Exception {
- MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- servletRequest.setMethod("put");
-
- assertEquals(null,
- HttpMethod.getMethodIfSupported(servletRequest, EnumSet.noneOf(HttpMethod.class)));
- }
-
- @Test
- public void getMethodRequestNotExists() throws Exception {
- MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- servletRequest.setMethod("test");
-
- assertEquals(null,
- HttpMethod.getMethodIfSupported(servletRequest, EnumSet.noneOf(HttpMethod.class)));
- }
-}
\ No newline at end of file
+ @Test
+ public void forName() throws Exception {
+ assertEquals(HttpMethod.DELETE, HttpMethod.forName("delete"));
+ assertEquals(HttpMethod.GET, HttpMethod.forName("get"));
+ assertEquals(HttpMethod.HEAD, HttpMethod.forName("head"));
+ assertEquals(HttpMethod.PATCH, HttpMethod.forName("patch"));
+ assertEquals(HttpMethod.POST, HttpMethod.forName("post"));
+ assertEquals(HttpMethod.PUT, HttpMethod.forName("put"));
+ assertEquals(HttpMethod.OPTIONS, HttpMethod.forName("options"));
+ assertEquals(null, HttpMethod.forName("test"));
+ }
+
+ @Test
+ public void getMethodNormal() throws Exception {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.setMethod("patch");
+
+ assertEquals(
+ HttpMethod.PATCH,
+ HttpMethod.getMethodIfSupported(servletRequest, EnumSet.allOf(HttpMethod.class)));
+ }
+
+ @Test
+ public void getMethodOverridden() throws Exception {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.setMethod("post");
+ servletRequest.addHeader(HttpHeader.METHOD_OVERRIDE, "patch");
+
+ assertEquals(
+ HttpMethod.PATCH,
+ HttpMethod.getMethodIfSupported(servletRequest, EnumSet.allOf(HttpMethod.class)));
+ }
+
+ @Test
+ public void getMethodOverriddenDoesNotExist() throws Exception {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.setMethod("post");
+ servletRequest.addHeader(HttpHeader.METHOD_OVERRIDE, "test");
+
+ assertEquals(
+ HttpMethod.POST,
+ HttpMethod.getMethodIfSupported(servletRequest, EnumSet.allOf(HttpMethod.class)));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getMethodNull() throws Exception {
+ HttpMethod.getMethodIfSupported(null, EnumSet.allOf(HttpMethod.class));
+ }
+
+ @Test
+ public void getMethodNotSupported() throws Exception {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.setMethod("put");
+
+ assertEquals(
+ null, HttpMethod.getMethodIfSupported(servletRequest, EnumSet.noneOf(HttpMethod.class)));
+ }
+
+ @Test
+ public void getMethodRequestNotExists() throws Exception {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.setMethod("test");
+
+ assertEquals(
+ null, HttpMethod.getMethodIfSupported(servletRequest, EnumSet.noneOf(HttpMethod.class)));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/ITTusFileUploadService.java b/src/test/java/me/desair/tus/server/ITTusFileUploadService.java
index 37f6dfa..f65712e 100644
--- a/src/test/java/me/desair/tus/server/ITTusFileUploadService.java
+++ b/src/test/java/me/desair/tus/server/ITTusFileUploadService.java
@@ -12,6 +12,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
@@ -23,8 +24,6 @@
import java.util.Arrays;
import java.util.Locale;
import java.util.UUID;
-import jakarta.servlet.http.HttpServletResponse;
-
import me.desair.tus.server.exception.TusException;
import me.desair.tus.server.upload.UploadInfo;
import me.desair.tus.server.util.Utils;
@@ -40,1336 +39,1409 @@
public class ITTusFileUploadService {
- protected static final String UPLOAD_URI = "/test/upload";
- protected static final String OWNER_KEY = "JOHN_DOE";
+ protected static final String UPLOAD_URI = "/test/upload";
+ protected static final String OWNER_KEY = "JOHN_DOE";
- private static final DateFormat mockDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
+ private static final DateFormat mockDateFormat =
+ new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
- protected MockHttpServletRequest servletRequest;
- protected MockHttpServletResponse servletResponse;
+ protected MockHttpServletRequest servletRequest;
+ protected MockHttpServletResponse servletResponse;
- protected TusFileUploadService tusFileUploadService;
+ protected TusFileUploadService tusFileUploadService;
- protected static Path storagePath;
+ protected static Path storagePath;
- @BeforeClass
- public static void setupDataFolder() throws IOException {
- storagePath = Paths.get("target", "tus", "data").toAbsolutePath();
- Files.createDirectories(storagePath);
- }
+ @BeforeClass
+ public static void setupDataFolder() throws IOException {
+ storagePath = Paths.get("target", "tus", "data").toAbsolutePath();
+ Files.createDirectories(storagePath);
+ }
- @AfterClass
- public static void destroyDataFolder() throws IOException {
- FileUtils.deleteDirectory(storagePath.toFile());
- }
+ @AfterClass
+ public static void destroyDataFolder() throws IOException {
+ FileUtils.deleteDirectory(storagePath.toFile());
+ }
- @Before
- public void setUp() {
- reset();
- tusFileUploadService = new TusFileUploadService()
+ @Before
+ public void setUp() {
+ reset();
+ tusFileUploadService =
+ new TusFileUploadService()
.withUploadURI(UPLOAD_URI)
.withStoragePath(storagePath.toAbsolutePath().toString())
.withMaxUploadSize(1073741824L)
.withUploadExpirationPeriod(2L * 24 * 60 * 60 * 1000)
.withDownloadFeature()
.withChunkedTransferDecoding(true);
+ }
+
+ protected void reset() {
+ servletRequest = new MockHttpServletRequest();
+ servletRequest.setRemoteAddr("192.168.1.1");
+ servletRequest.addHeader(HttpHeader.X_FORWARDED_FOR, "10.0.2.1, 123.231.12.4");
+ servletResponse = new MockHttpServletResponse();
+ }
+
+ @Test
+ public void testSupportedHttpMethods() {
+ assertThat(
+ tusFileUploadService.getSupportedHttpMethods(),
+ containsInAnyOrder(
+ HttpMethod.HEAD,
+ HttpMethod.OPTIONS,
+ HttpMethod.PATCH,
+ HttpMethod.POST,
+ HttpMethod.DELETE,
+ HttpMethod.GET));
+
+ assertThat(
+ tusFileUploadService.getEnabledFeatures(),
+ containsInAnyOrder(
+ "core",
+ "creation",
+ "checksum",
+ "termination",
+ "download",
+ "expiration",
+ "concatenation"));
+ }
+
+ @Test
+ public void testDisableFeature() throws Exception {
+ tusFileUploadService.disableTusExtension("download");
+ tusFileUploadService.disableTusExtension("termination");
+
+ assertThat(
+ tusFileUploadService.getSupportedHttpMethods(),
+ containsInAnyOrder(HttpMethod.HEAD, HttpMethod.OPTIONS, HttpMethod.PATCH, HttpMethod.POST));
+
+ assertThat(
+ tusFileUploadService.getEnabledFeatures(),
+ containsInAnyOrder("core", "creation", "checksum", "expiration", "concatenation"));
+
+ reset();
+ servletRequest.setMethod("GET");
+ servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+
+ reset();
+ servletRequest.setMethod("DELETE");
+ servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDisableCore() {
+ tusFileUploadService.disableTusExtension("core");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testWithFileStoreServiceNull() throws Exception {
+ tusFileUploadService.withUploadStorageService(null);
+ }
+
+ @Test
+ public void testProcessCompleteUpload() throws Exception {
+ String uploadContent = "This is my test upload content";
+
+ // Create upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, uploadContent.getBytes().length);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Upload bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, uploadContent.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "sha1 Mfhm5HaSPUf+pUakdMxARo4rvfQ=");
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setContent(uploadContent.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + uploadContent.getBytes().length);
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Check with HEAD request upload is complete
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + uploadContent.getBytes().length);
+ assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "" + uploadContent.getBytes().length);
+ assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
+ assertResponseHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Get upload info from service
+ UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
+ assertFalse(info.isUploadInProgress());
+ assertThat(info.getLength(), is((long) uploadContent.getBytes().length));
+ assertThat(info.getOffset(), is((long) uploadContent.getBytes().length));
+ assertThat(
+ info.getMetadata(), allOf(hasSize(1), hasEntry("filename", "world_domination_plan.pdf")));
+ assertThat(info.getCreatorIpAddresses(), is("10.0.2.1, 123.231.12.4, 192.168.1.1"));
+
+ // Try retrieving the uploaded bytes without owner key
+ try {
+ tusFileUploadService.getUploadedBytes(location);
+ fail();
+ } catch (TusException ex) {
+ assertThat(ex.getStatus(), is(404));
}
- protected void reset() {
- servletRequest = new MockHttpServletRequest();
- servletRequest.setRemoteAddr("192.168.1.1");
- servletRequest.addHeader(HttpHeader.X_FORWARDED_FOR, "10.0.2.1, 123.231.12.4");
- servletResponse = new MockHttpServletResponse();
- }
-
- @Test
- public void testSupportedHttpMethods() {
- assertThat(tusFileUploadService.getSupportedHttpMethods(), containsInAnyOrder(
- HttpMethod.HEAD, HttpMethod.OPTIONS, HttpMethod.PATCH,
- HttpMethod.POST, HttpMethod.DELETE, HttpMethod.GET));
-
- assertThat(tusFileUploadService.getEnabledFeatures(), containsInAnyOrder(
- "core", "creation", "checksum", "termination", "download", "expiration", "concatenation"));
- }
-
- @Test
- public void testDisableFeature() throws Exception {
- tusFileUploadService.disableTusExtension("download");
- tusFileUploadService.disableTusExtension("termination");
-
- assertThat(tusFileUploadService.getSupportedHttpMethods(), containsInAnyOrder(
- HttpMethod.HEAD, HttpMethod.OPTIONS, HttpMethod.PATCH,
- HttpMethod.POST));
-
- assertThat(tusFileUploadService.getEnabledFeatures(), containsInAnyOrder(
- "core", "creation", "checksum", "expiration", "concatenation"));
-
- reset();
- servletRequest.setMethod("GET");
- servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
-
- reset();
- servletRequest.setMethod("DELETE");
- servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testDisableCore() {
- tusFileUploadService.disableTusExtension("core");
- }
-
- @Test(expected = NullPointerException.class)
- public void testWithFileStoreServiceNull() throws Exception {
- tusFileUploadService.withUploadStorageService(null);
- }
-
- @Test
- public void testProcessCompleteUpload() throws Exception {
- String uploadContent = "This is my test upload content";
-
- //Create upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, uploadContent.getBytes().length);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Upload bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, uploadContent.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "sha1 Mfhm5HaSPUf+pUakdMxARo4rvfQ=");
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setContent(uploadContent.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + uploadContent.getBytes().length);
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Check with HEAD request upload is complete
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + uploadContent.getBytes().length);
- assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "" + uploadContent.getBytes().length);
- assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Get upload info from service
- UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
- assertFalse(info.isUploadInProgress());
- assertThat(info.getLength(), is((long) uploadContent.getBytes().length));
- assertThat(info.getOffset(), is((long) uploadContent.getBytes().length));
- assertThat(info.getMetadata(), allOf(
- hasSize(1),
- hasEntry("filename", "world_domination_plan.pdf")
- )
- );
- assertThat(info.getCreatorIpAddresses(), is("10.0.2.1, 123.231.12.4, 192.168.1.1"));
-
- //Try retrieving the uploaded bytes without owner key
- try {
- tusFileUploadService.getUploadedBytes(location);
- fail();
- } catch (TusException ex) {
- assertThat(ex.getStatus(), is(404));
- }
-
- //Get uploaded bytes from service
- try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, OWNER_KEY)) {
- assertThat(IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
- is("This is my test upload content"));
- }
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Download the upload
- reset();
- servletRequest.setMethod("GET");
- servletRequest.setRequestURI(location);
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "" + uploadContent.getBytes().length);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
- assertResponseStatus(HttpServletResponse.SC_OK);
- assertThat(servletResponse.getContentAsString(), is("This is my test upload content"));
-
- //Pretend that we processed the upload and that we can remove it
- tusFileUploadService.deleteUpload(location, OWNER_KEY);
-
- //Check that the upload is really gone
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- }
-
- @Test
- public void testTerminateViaHttpRequest() throws Exception {
- String uploadContent = "This is my terminated test upload";
-
- //Create upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, uploadContent.getBytes().length);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Upload bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, uploadContent.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setContent(uploadContent.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + uploadContent.getBytes().length);
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Download the upload to make sure it was uploaded correctly
- reset();
- servletRequest.setMethod("GET");
- servletRequest.setRequestURI(location);
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "" + uploadContent.getBytes().length);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
- assertResponseStatus(HttpServletResponse.SC_OK);
- assertThat(servletResponse.getContentAsString(), is("This is my terminated test upload"));
-
- //Terminate the upload so that the server can remove it
- reset();
- servletRequest.setMethod("DELETE");
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setRequestURI(location);
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Check that the upload is really gone
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- }
-
- @Test
- public void testProcessUploadTwoParts() throws Exception {
- String part1 = "29\r\nThis is the first part of my test upload "
- + "\r\n0\r\nUpload-Checksum: sha1 n5RQbRwM6UVAD+9iuHEmnN6HCGQ=";
- String part2 = "1C\r\nand this is the second part."
- + "\r\n0\r\nUpload-Checksum: sha1 oNge323kGFKICxp+Me5xJgPvGEM=";
-
- //Create upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "69");
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Upload part 1 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "41");
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
- servletRequest.setContent(part1.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "41");
-
- //Check with service that upload is still in progress
- UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
- assertTrue(info.isUploadInProgress());
- assertThat(info.getLength(), is(69L));
- assertThat(info.getOffset(), is(41L));
- assertThat(info.getMetadata(), allOf(
- hasSize(1),
- hasEntry("filename", "world_domination_plan.pdf")
- )
- );
- assertThat(info.getCreatorIpAddresses(), is("10.0.2.1, 123.231.12.4, 192.168.1.1"));
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Verify that we cannot download an in-progress upload
- reset();
- servletRequest.setMethod("GET");
- servletRequest.setRequestURI(location);
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(422);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertThat(servletResponse.getContentAsString(), is(""));
-
- //Upload part 2 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "28");
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, "41");
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
- servletRequest.setContent(part2.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "69");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Check with HEAD request upload is complete
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "69");
- assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "69");
- assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Get upload info from service
- info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
- assertFalse(info.isUploadInProgress());
- assertThat(info.getLength(), is(69L));
- assertThat(info.getOffset(), is(69L));
- assertThat(info.getMetadata(), allOf(
- hasSize(1),
- hasEntry("filename", "world_domination_plan.pdf")
- )
- );
- assertThat(info.getCreatorIpAddresses(), is("10.0.2.1, 123.231.12.4, 192.168.1.1"));
-
- //Get uploaded bytes from service
- try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, OWNER_KEY)) {
- assertThat(IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
- is("This is the first part of my test upload and this is the second part."));
- }
- }
-
- @Test
- public void testProcessUploadDeferredLength() throws Exception {
- String part1 = "When sending this part, we don't know the length and ";
- String part2 = "when sending this part, we know the length but the upload is not complete. ";
- String part3 = "Finally when sending the third part, the upload is complete.";
-
- //Create upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- Long expirationTimestampBefore =
- Long.parseLong(String.valueOf(
- mockDateFormat.parse(servletResponse.getHeader(HttpHeader.UPLOAD_EXPIRES)).getTime()));
-
- String location = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Upload part 1 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part1.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setContent(part1.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part1.getBytes().length);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Check with service that upload is still in progress
- UploadInfo info = tusFileUploadService.getUploadInfo(location, null);
- assertTrue(info.isUploadInProgress());
- assertThat(info.getLength(), is(nullValue()));
- assertThat(info.getOffset(), is((long) part1.getBytes().length));
- assertThat(info.getMetadata(), allOf(
- hasSize(1),
- hasEntry("filename", "world_domination_plan.pdf")
- )
- );
- assertThat(info.getCreatorIpAddresses(), is("10.0.2.1, 123.231.12.4, 192.168.1.1"));
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Check with HEAD request length is still not known
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part1.getBytes().length);
- assertResponseHeader(HttpHeader.UPLOAD_DEFER_LENGTH, "1");
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Upload part 2 bytes with length
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part2.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, part1.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, (part1 + part2 + part3).getBytes().length);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setContent(part2.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + (part1 + part2).getBytes().length);
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Check with HEAD request length is known
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + (part1 + part2).getBytes().length);
- assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "" + (part1 + part2 + part3).getBytes().length);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
- assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- info = tusFileUploadService.getUploadInfo(location, null);
- assertTrue(info.isUploadInProgress());
- assertThat(info.getLength(), is((long) (part1 + part2 + part3).getBytes().length));
-
- //check that expiration timestamp was updated
- assertThat(info.getExpirationTimestamp(), greaterThan(expirationTimestampBefore));
-
- //Upload part 3 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part3.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, (part1 + part2).getBytes().length);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setContent(part3.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + (part1 + part2 + part3).getBytes().length);
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Get upload info from service
- info = tusFileUploadService.getUploadInfo(location, null);
- assertFalse(info.isUploadInProgress());
- assertThat(info.getLength(), is((long) (part1 + part2 + part3).getBytes().length));
- assertThat(info.getOffset(), is((long) (part1 + part2 + part3).getBytes().length));
- assertThat(info.getMetadata(), allOf(
- hasSize(1),
- hasEntry("filename", "world_domination_plan.pdf")
- )
- );
-
- //Get uploaded bytes from service
- try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, null)) {
- assertThat(IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
- is("When sending this part, we don't know the length and " +
- "when sending this part, we know the length but the upload is not complete. " +
- "Finally when sending the third part, the upload is complete."));
- }
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Download the upload
- reset();
- servletRequest.setMethod("GET");
- servletRequest.setRequestURI(location);
-
- tusFileUploadService.process(servletRequest, servletResponse, null);
- assertResponseStatus(HttpServletResponse.SC_OK);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "" + (part1 + part2 + part3).getBytes().length);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
- assertThat(servletResponse.getContentAsString(), is(
- "When sending this part, we don't know the length and " +
- "when sending this part, we know the length but the upload is not complete. " +
- "Finally when sending the third part, the upload is complete."));
-
- }
-
- @Test
- public void testProcessUploadInvalidChecksumSecondPart() throws Exception {
- String part1 = "29\r\nThis is the first part of my test upload " +
- "\r\n0\r\nUPLOAD-CHECKSUM: sha1 n5RQbRwM6UVAD+9iuHEmnN6HCGQ=";
- String part2 = "1C\r\nand this is the second part." +
- "\r\n0\r\nupload-checksum: sha1 invalid";
-
- //Create upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "69");
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Upload part 1 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "41");
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
- servletRequest.setContent(part1.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "41");
-
- Long expirationTimestampBefore =
- Long.parseLong(String.valueOf(
- mockDateFormat.parse(servletResponse.getHeader(HttpHeader.UPLOAD_EXPIRES)).getTime()));
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Upload part 2 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "28");
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, "41");
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
- servletRequest.setContent(part2.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
-
- //We expect the server to return a checksum mismatch error
- assertResponseStatus(460);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
-
- //Check that upload info is still from the first patch
- UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
- assertTrue(info.isUploadInProgress());
- assertThat(info.getLength(), is(69L));
- assertThat(info.getOffset(), is(41L));
- assertThat(info.getMetadata(), allOf(
- hasSize(1),
- hasEntry("filename", "world_domination_plan.pdf")
- )
- );
-
- //check that expiration timestamp was updated
- assertThat(info.getExpirationTimestamp(), greaterThan(expirationTimestampBefore));
-
- //We only stored the first valid part
- try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, OWNER_KEY)) {
- assertThat(IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
- is("This is the first part of my test upload "));
- }
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Terminate our in progress upload
- reset();
- servletRequest.setMethod("DELETE");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
-
- //We expect the server to return a no content code to indicate successful deletion
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Check that the upload is really gone
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- }
-
- @Test
- public void testCleanupExpiredUpload() throws Exception {
- //Set the expiration period to 500 ms
- tusFileUploadService.withUploadExpirationPeriod(500L);
-
- String part1 = "This is the first part of my test upload";
- //Create upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, part1.getBytes().length + 20L);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Upload part 1 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part1.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setContent(part1.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part1.getBytes().length);
-
- //Check with service that upload is still in progress
- UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
- assertTrue(info.isUploadInProgress());
- assertThat(info.getLength(), is(part1.getBytes().length + 20L));
- assertThat(info.getOffset(), is(Long.valueOf(part1.getBytes().length)));
-
- //Now wait until the upload expired and run the cleanup
- Utils.sleep(1000L);
- tusFileUploadService.cleanup();
-
- //Check with HEAD request that the upload is gone
- //If a Client does attempt to resume an upload which has since been removed by the Server,
- //the Server SHOULD respond with the404 Not Found or 410 Gone status.
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
+ // Get uploaded bytes from service
+ try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, OWNER_KEY)) {
+ assertThat(
+ IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
+ is("This is my test upload content"));
}
- @Test
- public void testConcatenationCompleted() throws Exception {
- String part1 = "29\r\nThis is the first part of my test upload " +
- "\r\n0\r\nUpload-Checksum: sha1 n5RQbRwM6UVAD+9iuHEmnN6HCGQ=";
- String part2 = "1C\r\nand this is the second part." +
- "\r\n0\r\nUpload-Checksum: sha1 oNge323kGFKICxp+Me5xJgPvGEM=";
-
- //Create first upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "41");
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location1 = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Upload part 1 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location1);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "41");
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
- servletRequest.setContent(part1.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "41");
-
- //Make sure cleanup does not interfere with this test
- tusFileUploadService.cleanup();
-
- //Create the second upload
- reset();
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "28");
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location2 = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Upload part 2 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location2);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "28");
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, "0");
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
- servletRequest.setContent(part2.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "28");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Create the final concatenated upload
- reset();
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final ; " + location1 + " " + location2);
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA,
- "filename d29ybGRfZG9taW5hdGlvbl9tYXBfY29uY2F0ZW5hdGVkLnBkZg==");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Check with HEAD request upload is complete
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "69");
- assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "69");
- assertResponseHeader(HttpHeader.UPLOAD_CONCAT, "final ; " + location1 + " " + location2);
- assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA,
- "filename d29ybGRfZG9taW5hdGlvbl9tYXBfY29uY2F0ZW5hdGVkLnBkZg==");
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Get upload info from service
- UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
- assertFalse(info.isUploadInProgress());
- assertThat(info.getLength(), is(69L));
- assertThat(info.getOffset(), is(69L));
- assertThat(info.isUploadInProgress(), is(false));
- assertThat(info.getMetadata(), allOf(
- hasSize(1),
- hasEntry("filename", "world_domination_map_concatenated.pdf")
- )
- );
- assertThat(info.getCreatorIpAddresses(), is("10.0.2.1, 123.231.12.4, 192.168.1.1"));
-
- //Download the upload
- reset();
- servletRequest.setMethod("GET");
- servletRequest.setRequestURI(location);
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_OK);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "69");
- assertResponseHeader(HttpHeader.UPLOAD_METADATA,
- "filename d29ybGRfZG9taW5hdGlvbl9tYXBfY29uY2F0ZW5hdGVkLnBkZg==");
- assertThat(servletResponse.getContentAsString(),
- is("This is the first part of my test upload and this is the second part."));
-
- //Get uploaded bytes from service
- try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, OWNER_KEY)) {
- assertThat(IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
- is("This is the first part of my test upload and this is the second part."));
- }
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Download the upload
+ reset();
+ servletRequest.setMethod("GET");
+ servletRequest.setRequestURI(location);
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "" + uploadContent.getBytes().length);
+ assertResponseHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+ assertResponseStatus(HttpServletResponse.SC_OK);
+ assertThat(servletResponse.getContentAsString(), is("This is my test upload content"));
+
+ // Pretend that we processed the upload and that we can remove it
+ tusFileUploadService.deleteUpload(location, OWNER_KEY);
+
+ // Check that the upload is really gone
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ }
+
+ @Test
+ public void testTerminateViaHttpRequest() throws Exception {
+ String uploadContent = "This is my terminated test upload";
+
+ // Create upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, uploadContent.getBytes().length);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Upload bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, uploadContent.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setContent(uploadContent.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + uploadContent.getBytes().length);
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Download the upload to make sure it was uploaded correctly
+ reset();
+ servletRequest.setMethod("GET");
+ servletRequest.setRequestURI(location);
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "" + uploadContent.getBytes().length);
+ assertResponseHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+ assertResponseStatus(HttpServletResponse.SC_OK);
+ assertThat(servletResponse.getContentAsString(), is("This is my terminated test upload"));
+
+ // Terminate the upload so that the server can remove it
+ reset();
+ servletRequest.setMethod("DELETE");
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setRequestURI(location);
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Check that the upload is really gone
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ }
+
+ @Test
+ public void testProcessUploadTwoParts() throws Exception {
+ String part1 =
+ "29\r\nThis is the first part of my test upload "
+ + "\r\n0\r\nUpload-Checksum: sha1 n5RQbRwM6UVAD+9iuHEmnN6HCGQ=";
+ String part2 =
+ "1C\r\nand this is the second part."
+ + "\r\n0\r\nUpload-Checksum: sha1 oNge323kGFKICxp+Me5xJgPvGEM=";
+
+ // Create upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "69");
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Upload part 1 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "41");
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
+ servletRequest.setContent(part1.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "41");
+
+ // Check with service that upload is still in progress
+ UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
+ assertTrue(info.isUploadInProgress());
+ assertThat(info.getLength(), is(69L));
+ assertThat(info.getOffset(), is(41L));
+ assertThat(
+ info.getMetadata(), allOf(hasSize(1), hasEntry("filename", "world_domination_plan.pdf")));
+ assertThat(info.getCreatorIpAddresses(), is("10.0.2.1, 123.231.12.4, 192.168.1.1"));
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Verify that we cannot download an in-progress upload
+ reset();
+ servletRequest.setMethod("GET");
+ servletRequest.setRequestURI(location);
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(422);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertThat(servletResponse.getContentAsString(), is(""));
+
+ // Upload part 2 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "28");
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, "41");
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
+ servletRequest.setContent(part2.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "69");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Check with HEAD request upload is complete
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "69");
+ assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "69");
+ assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
+ assertResponseHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Get upload info from service
+ info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
+ assertFalse(info.isUploadInProgress());
+ assertThat(info.getLength(), is(69L));
+ assertThat(info.getOffset(), is(69L));
+ assertThat(
+ info.getMetadata(), allOf(hasSize(1), hasEntry("filename", "world_domination_plan.pdf")));
+ assertThat(info.getCreatorIpAddresses(), is("10.0.2.1, 123.231.12.4, 192.168.1.1"));
+
+ // Get uploaded bytes from service
+ try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, OWNER_KEY)) {
+ assertThat(
+ IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
+ is("This is the first part of my test upload and this is the second part."));
}
-
- @Test
- public void testConcatenationUnfinished() throws Exception {
- String part1 = "When sending this part, the final upload was already created. ";
- String part2 = "This is the second part of our concatenated upload. ";
- String part3 = "Finally when sending the third part, the final upload is complete.";
-
- //Create upload part 1
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename cGFydDEucGRm");
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location1 = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- reset();
- //Create upload part 2
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename cGFydDIucGRm");
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location2 = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- reset();
- //Create upload part 3
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename cGFydDMucGRm");
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location3 = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Upload part 2 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location2);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part2.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, part2.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setContent(part2.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part2.getBytes().length);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- reset();
- //Create final upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final;" + location1 + " " + location2 + " " + location3);
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename ZmluYWwucGRm");
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String locationFinal = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Check with HEAD request that length of final upload is undefined
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(locationFinal);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNull(HttpHeader.UPLOAD_OFFSET);
- assertResponseHeaderNull(HttpHeader.UPLOAD_LENGTH);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename ZmluYWwucGRm");
- assertResponseHeader(HttpHeader.UPLOAD_CONCAT, "final;" + location1 + " " + location2 + " " + location3);
- assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Verify that we cannot download an unfinished final upload
- reset();
- servletRequest.setMethod("GET");
- servletRequest.setRequestURI(locationFinal);
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseStatus(422);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertThat(servletResponse.getContentAsString(), is(""));
-
- //Upload part 1 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location1);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part1.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, part1.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setContent(part1.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part1.getBytes().length);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Upload part 3 bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location3);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part3.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, part3.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setContent(part3.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part3.getBytes().length);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Check with HEAD request length of final upload is known
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(locationFinal);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + (part1 + part2 + part3).getBytes().length);
- assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "" + (part1 + part2 + part3).getBytes().length);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename ZmluYWwucGRm");
- assertResponseHeader(HttpHeader.UPLOAD_CONCAT, "final;" + location1 + " " + location2 + " " + location3);
- assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Download the upload
- reset();
- servletRequest.setMethod("GET");
- servletRequest.setRequestURI(locationFinal);
-
- tusFileUploadService.process(servletRequest, servletResponse, null);
- assertResponseStatus(HttpServletResponse.SC_OK);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "" + (part1 + part2 + part3).getBytes().length);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename ZmluYWwucGRm");
- assertThat(servletResponse.getContentAsString(), is(
- "When sending this part, the final upload was already created. " +
- "This is the second part of our concatenated upload. " +
- "Finally when sending the third part, the final upload is complete."));
-
- //Get uploaded bytes from service
- try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(locationFinal, null)) {
- assertThat(IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
- is("When sending this part, the final upload was already created. " +
- "This is the second part of our concatenated upload. " +
- "Finally when sending the third part, the final upload is complete."));
- }
- }
-
- @Test
- public void testChunkedDecodingDisabledAndRegexUploadURI() throws Exception {
- String chunkedContent = "1B;test=value\r\nThis upload looks chunked, \r\n"
- + "D\r\nbut it's not!\r\n"
- + "\r\n0\r\n";
-
- //Create service without chunked decoding
- tusFileUploadService = new TusFileUploadService()
- .withUploadURI("/users/[0-9]+/files/upload")
- .withStoragePath(storagePath.toAbsolutePath().toString())
- .withDownloadFeature();
-
- //Create upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI("/users/98765/files/upload");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "67");
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNull(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location = servletResponse.getHeader(HttpHeader.LOCATION);
-
- //Upload content
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "67");
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
- servletRequest.setContent(chunkedContent.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNull(HttpHeader.UPLOAD_EXPIRES);
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "67");
-
- //Check with HEAD request upload is complete
- reset();
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "67");
- assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "67");
- assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
- assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Get upload info from service
- UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
- assertFalse(info.isUploadInProgress());
- assertThat(info.getLength(), is(67L));
- assertThat(info.getOffset(), is(67L));
- assertThat(info.getMetadata(), allOf(
- hasSize(1),
- hasEntry("filename", "world_domination_plan.pdf")
- )
- );
-
- //Get uploaded bytes from service
- try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, OWNER_KEY)) {
- assertThat(IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
- is("1B;test=value\r\nThis upload looks chunked, \r\n"
- + "D\r\nbut it's not!\r\n"
- + "\r\n0\r\n"));
- }
+ }
+
+ @Test
+ public void testProcessUploadDeferredLength() throws Exception {
+ String part1 = "When sending this part, we don't know the length and ";
+ String part2 = "when sending this part, we know the length but the upload is not complete. ";
+ String part3 = "Finally when sending the third part, the upload is complete.";
+
+ // Create upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ Long expirationTimestampBefore =
+ Long.parseLong(
+ String.valueOf(
+ mockDateFormat
+ .parse(servletResponse.getHeader(HttpHeader.UPLOAD_EXPIRES))
+ .getTime()));
+
+ String location =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Upload part 1 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part1.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setContent(part1.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part1.getBytes().length);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Check with service that upload is still in progress
+ UploadInfo info = tusFileUploadService.getUploadInfo(location, null);
+ assertTrue(info.isUploadInProgress());
+ assertThat(info.getLength(), is(nullValue()));
+ assertThat(info.getOffset(), is((long) part1.getBytes().length));
+ assertThat(
+ info.getMetadata(), allOf(hasSize(1), hasEntry("filename", "world_domination_plan.pdf")));
+ assertThat(info.getCreatorIpAddresses(), is("10.0.2.1, 123.231.12.4, 192.168.1.1"));
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Check with HEAD request length is still not known
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part1.getBytes().length);
+ assertResponseHeader(HttpHeader.UPLOAD_DEFER_LENGTH, "1");
+ assertResponseHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Upload part 2 bytes with length
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part2.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, part1.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, (part1 + part2 + part3).getBytes().length);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setContent(part2.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + (part1 + part2).getBytes().length);
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Check with HEAD request length is known
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + (part1 + part2).getBytes().length);
+ assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "" + (part1 + part2 + part3).getBytes().length);
+ assertResponseHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+ assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ info = tusFileUploadService.getUploadInfo(location, null);
+ assertTrue(info.isUploadInProgress());
+ assertThat(info.getLength(), is((long) (part1 + part2 + part3).getBytes().length));
+
+ // check that expiration timestamp was updated
+ assertThat(info.getExpirationTimestamp(), greaterThan(expirationTimestampBefore));
+
+ // Upload part 3 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part3.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, (part1 + part2).getBytes().length);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setContent(part3.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + (part1 + part2 + part3).getBytes().length);
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Get upload info from service
+ info = tusFileUploadService.getUploadInfo(location, null);
+ assertFalse(info.isUploadInProgress());
+ assertThat(info.getLength(), is((long) (part1 + part2 + part3).getBytes().length));
+ assertThat(info.getOffset(), is((long) (part1 + part2 + part3).getBytes().length));
+ assertThat(
+ info.getMetadata(), allOf(hasSize(1), hasEntry("filename", "world_domination_plan.pdf")));
+
+ // Get uploaded bytes from service
+ try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, null)) {
+ assertThat(
+ IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
+ is(
+ "When sending this part, we don't know the length and "
+ + "when sending this part, we know the length but the upload is not complete. "
+ + "Finally when sending the third part, the upload is complete."));
}
- @Test
- public void testOptions() throws Exception {
- //Do options request and check response headers
- servletRequest.setMethod("OPTIONS");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
-
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.TUS_VERSION, "1.0.0");
- assertResponseHeader(HttpHeader.TUS_MAX_SIZE, "1073741824");
- assertResponseHeader(HttpHeader.TUS_CHECKSUM_ALGORITHM, "md5", "sha1", "sha256", "sha384", "sha512");
- assertResponseHeader(HttpHeader.TUS_EXTENSION, "creation", "creation-defer-length", "checksum",
- "checksum-trailer", "termination", "download", "expiration",
- "concatenation", "concatenation-unfinished");
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Download the upload
+ reset();
+ servletRequest.setMethod("GET");
+ servletRequest.setRequestURI(location);
+
+ tusFileUploadService.process(servletRequest, servletResponse, null);
+ assertResponseStatus(HttpServletResponse.SC_OK);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "" + (part1 + part2 + part3).getBytes().length);
+ assertResponseHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+ assertThat(
+ servletResponse.getContentAsString(),
+ is(
+ "When sending this part, we don't know the length and "
+ + "when sending this part, we know the length but the upload is not complete. "
+ + "Finally when sending the third part, the upload is complete."));
+ }
+
+ @Test
+ public void testProcessUploadInvalidChecksumSecondPart() throws Exception {
+ String part1 =
+ "29\r\nThis is the first part of my test upload "
+ + "\r\n0\r\nUPLOAD-CHECKSUM: sha1 n5RQbRwM6UVAD+9iuHEmnN6HCGQ=";
+ String part2 = "1C\r\nand this is the second part." + "\r\n0\r\nupload-checksum: sha1 invalid";
+
+ // Create upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "69");
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Upload part 1 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "41");
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
+ servletRequest.setContent(part1.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "41");
+
+ Long expirationTimestampBefore =
+ Long.parseLong(
+ String.valueOf(
+ mockDateFormat
+ .parse(servletResponse.getHeader(HttpHeader.UPLOAD_EXPIRES))
+ .getTime()));
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Upload part 2 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "28");
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, "41");
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
+ servletRequest.setContent(part2.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+
+ // We expect the server to return a checksum mismatch error
+ assertResponseStatus(460);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+
+ // Check that upload info is still from the first patch
+ UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
+ assertTrue(info.isUploadInProgress());
+ assertThat(info.getLength(), is(69L));
+ assertThat(info.getOffset(), is(41L));
+ assertThat(
+ info.getMetadata(), allOf(hasSize(1), hasEntry("filename", "world_domination_plan.pdf")));
+
+ // check that expiration timestamp was updated
+ assertThat(info.getExpirationTimestamp(), greaterThan(expirationTimestampBefore));
+
+ // We only stored the first valid part
+ try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, OWNER_KEY)) {
+ assertThat(
+ IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
+ is("This is the first part of my test upload "));
}
- @Test
- public void testHeadOnNonExistingUpload() throws Exception {
- servletRequest.setMethod("HEAD");
- servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Terminate our in progress upload
+ reset();
+ servletRequest.setMethod("DELETE");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+
+ // We expect the server to return a no content code to indicate successful deletion
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Check that the upload is really gone
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ }
+
+ @Test
+ public void testCleanupExpiredUpload() throws Exception {
+ // Set the expiration period to 500 ms
+ tusFileUploadService.withUploadExpirationPeriod(500L);
+
+ String part1 = "This is the first part of my test upload";
+ // Create upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, part1.getBytes().length + 20L);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Upload part 1 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part1.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setContent(part1.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part1.getBytes().length);
+
+ // Check with service that upload is still in progress
+ UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
+ assertTrue(info.isUploadInProgress());
+ assertThat(info.getLength(), is(part1.getBytes().length + 20L));
+ assertThat(info.getOffset(), is(Long.valueOf(part1.getBytes().length)));
+
+ // Now wait until the upload expired and run the cleanup
+ Utils.sleep(1000L);
+ tusFileUploadService.cleanup();
+
+ // Check with HEAD request that the upload is gone
+ // If a Client does attempt to resume an upload which has since been removed by the Server,
+ // the Server SHOULD respond with the404 Not Found or 410 Gone status.
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ @Test
+ public void testConcatenationCompleted() throws Exception {
+ String part1 =
+ "29\r\nThis is the first part of my test upload "
+ + "\r\n0\r\nUpload-Checksum: sha1 n5RQbRwM6UVAD+9iuHEmnN6HCGQ=";
+ String part2 =
+ "1C\r\nand this is the second part."
+ + "\r\n0\r\nUpload-Checksum: sha1 oNge323kGFKICxp+Me5xJgPvGEM=";
+
+ // Create first upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "41");
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location1 =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Upload part 1 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location1);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "41");
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
+ servletRequest.setContent(part1.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "41");
+
+ // Make sure cleanup does not interfere with this test
+ tusFileUploadService.cleanup();
+
+ // Create the second upload
+ reset();
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "28");
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location2 =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Upload part 2 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location2);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "28");
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, "0");
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
+ servletRequest.setContent(part2.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "28");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Create the final concatenated upload
+ reset();
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final ; " + location1 + " " + location2);
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_METADATA,
+ "filename d29ybGRfZG9taW5hdGlvbl9tYXBfY29uY2F0ZW5hdGVkLnBkZg==");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Check with HEAD request upload is complete
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "69");
+ assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "69");
+ assertResponseHeader(HttpHeader.UPLOAD_CONCAT, "final ; " + location1 + " " + location2);
+ assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
+ assertResponseHeader(
+ HttpHeader.UPLOAD_METADATA,
+ "filename d29ybGRfZG9taW5hdGlvbl9tYXBfY29uY2F0ZW5hdGVkLnBkZg==");
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Get upload info from service
+ UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
+ assertFalse(info.isUploadInProgress());
+ assertThat(info.getLength(), is(69L));
+ assertThat(info.getOffset(), is(69L));
+ assertThat(info.isUploadInProgress(), is(false));
+ assertThat(
+ info.getMetadata(),
+ allOf(hasSize(1), hasEntry("filename", "world_domination_map_concatenated.pdf")));
+ assertThat(info.getCreatorIpAddresses(), is("10.0.2.1, 123.231.12.4, 192.168.1.1"));
+
+ // Download the upload
+ reset();
+ servletRequest.setMethod("GET");
+ servletRequest.setRequestURI(location);
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_OK);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "69");
+ assertResponseHeader(
+ HttpHeader.UPLOAD_METADATA,
+ "filename d29ybGRfZG9taW5hdGlvbl9tYXBfY29uY2F0ZW5hdGVkLnBkZg==");
+ assertThat(
+ servletResponse.getContentAsString(),
+ is("This is the first part of my test upload and this is the second part."));
+
+ // Get uploaded bytes from service
+ try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, OWNER_KEY)) {
+ assertThat(
+ IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
+ is("This is the first part of my test upload and this is the second part."));
}
-
- @Test
- public void testInvalidTusResumable() throws Exception {
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "2.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- }
-
- @Test
- public void testMaxUploadLengthExceeded() throws Exception {
- tusFileUploadService.withMaxUploadSize(10L);
-
- String uploadContent = "This is upload is too long";
-
- //Create upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, uploadContent.getBytes().length);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ }
+
+ @Test
+ public void testConcatenationUnfinished() throws Exception {
+ String part1 = "When sending this part, the final upload was already created. ";
+ String part2 = "This is the second part of our concatenated upload. ";
+ String part3 = "Finally when sending the third part, the final upload is complete.";
+
+ // Create upload part 1
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
+ servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename cGFydDEucGRm");
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location1 =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ reset();
+ // Create upload part 2
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
+ servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename cGFydDIucGRm");
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location2 =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ reset();
+ // Create upload part 3
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
+ servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename cGFydDMucGRm");
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location3 =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Upload part 2 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location2);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part2.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, part2.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setContent(part2.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part2.getBytes().length);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ reset();
+ // Create final upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_CONCAT, "final;" + location1 + " " + location2 + " " + location3);
+ servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "filename ZmluYWwucGRm");
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String locationFinal =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Check with HEAD request that length of final upload is undefined
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(locationFinal);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNull(HttpHeader.UPLOAD_OFFSET);
+ assertResponseHeaderNull(HttpHeader.UPLOAD_LENGTH);
+ assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename ZmluYWwucGRm");
+ assertResponseHeader(
+ HttpHeader.UPLOAD_CONCAT, "final;" + location1 + " " + location2 + " " + location3);
+ assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Verify that we cannot download an unfinished final upload
+ reset();
+ servletRequest.setMethod("GET");
+ servletRequest.setRequestURI(locationFinal);
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseStatus(422);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertThat(servletResponse.getContentAsString(), is(""));
+
+ // Upload part 1 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location1);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part1.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, part1.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setContent(part1.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part1.getBytes().length);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Upload part 3 bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location3);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, part3.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, part3.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setContent(part3.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + part3.getBytes().length);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Check with HEAD request length of final upload is known
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(locationFinal);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + (part1 + part2 + part3).getBytes().length);
+ assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "" + (part1 + part2 + part3).getBytes().length);
+ assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename ZmluYWwucGRm");
+ assertResponseHeader(
+ HttpHeader.UPLOAD_CONCAT, "final;" + location1 + " " + location2 + " " + location3);
+ assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Download the upload
+ reset();
+ servletRequest.setMethod("GET");
+ servletRequest.setRequestURI(locationFinal);
+
+ tusFileUploadService.process(servletRequest, servletResponse, null);
+ assertResponseStatus(HttpServletResponse.SC_OK);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "" + (part1 + part2 + part3).getBytes().length);
+ assertResponseHeader(HttpHeader.UPLOAD_METADATA, "filename ZmluYWwucGRm");
+ assertThat(
+ servletResponse.getContentAsString(),
+ is(
+ "When sending this part, the final upload was already created. "
+ + "This is the second part of our concatenated upload. "
+ + "Finally when sending the third part, the final upload is complete."));
+
+ // Get uploaded bytes from service
+ try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(locationFinal, null)) {
+ assertThat(
+ IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
+ is(
+ "When sending this part, the final upload was already created. "
+ + "This is the second part of our concatenated upload. "
+ + "Finally when sending the third part, the final upload is complete."));
}
+ }
- @Test
- public void testInvalidMethods() throws Exception {
- servletRequest.setMethod("PUT");
- servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
-
- reset();
- servletRequest.setMethod("CONNECT");
- servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
-
- reset();
- servletRequest.setMethod("TRACE");
- servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ @Test
+ public void testChunkedDecodingDisabledAndRegexUploadURI() throws Exception {
+ String chunkedContent =
+ "1B;test=value\r\nThis upload looks chunked, \r\n" + "D\r\nbut it's not!\r\n" + "\r\n0\r\n";
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
-
- }
-
- protected void assertResponseHeader(final String header, final String value) {
- assertThat(servletResponse.getHeader(header), is(value));
- }
-
- protected void assertResponseHeader(final String header, final String... values) {
- assertThat(Arrays.asList(servletResponse.getHeader(header).split(",")),
- containsInAnyOrder(values));
- }
-
- protected void assertResponseHeaderNotBlank(final String header) {
- assertTrue(StringUtils.isNotBlank(servletResponse.getHeader(header)));
- }
-
- protected void assertResponseHeaderNull(final String header) {
- assertTrue(servletResponse.getHeader(header) == null);
- }
-
- protected void assertResponseStatus(final int httpStatus) {
- assertThat(servletResponse.getStatus(), is(httpStatus));
+ // Create service without chunked decoding
+ tusFileUploadService =
+ new TusFileUploadService()
+ .withUploadURI("/users/[0-9]+/files/upload")
+ .withStoragePath(storagePath.toAbsolutePath().toString())
+ .withDownloadFeature();
+
+ // Create upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI("/users/98765/files/upload");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "67");
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNull(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location = servletResponse.getHeader(HttpHeader.LOCATION);
+
+ // Upload content
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, "67");
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
+ servletRequest.setContent(chunkedContent.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNull(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "67");
+
+ // Check with HEAD request upload is complete
+ reset();
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "67");
+ assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "67");
+ assertResponseHeaderNull(HttpHeader.UPLOAD_DEFER_LENGTH);
+ assertResponseHeader(
+ HttpHeader.UPLOAD_METADATA, "filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Get upload info from service
+ UploadInfo info = tusFileUploadService.getUploadInfo(location, OWNER_KEY);
+ assertFalse(info.isUploadInProgress());
+ assertThat(info.getLength(), is(67L));
+ assertThat(info.getOffset(), is(67L));
+ assertThat(
+ info.getMetadata(), allOf(hasSize(1), hasEntry("filename", "world_domination_plan.pdf")));
+
+ // Get uploaded bytes from service
+ try (InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(location, OWNER_KEY)) {
+ assertThat(
+ IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
+ is(
+ "1B;test=value\r\nThis upload looks chunked, \r\n"
+ + "D\r\nbut it's not!\r\n"
+ + "\r\n0\r\n"));
}
-
-}
\ No newline at end of file
+ }
+
+ @Test
+ public void testOptions() throws Exception {
+ // Do options request and check response headers
+ servletRequest.setMethod("OPTIONS");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.TUS_VERSION, "1.0.0");
+ assertResponseHeader(HttpHeader.TUS_MAX_SIZE, "1073741824");
+ assertResponseHeader(
+ HttpHeader.TUS_CHECKSUM_ALGORITHM, "md5", "sha1", "sha256", "sha384", "sha512");
+ assertResponseHeader(
+ HttpHeader.TUS_EXTENSION,
+ "creation",
+ "creation-defer-length",
+ "checksum",
+ "checksum-trailer",
+ "termination",
+ "download",
+ "expiration",
+ "concatenation",
+ "concatenation-unfinished");
+ }
+
+ @Test
+ public void testHeadOnNonExistingUpload() throws Exception {
+ servletRequest.setMethod("HEAD");
+ servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ }
+
+ @Test
+ public void testInvalidTusResumable() throws Exception {
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "2.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ }
+
+ @Test
+ public void testMaxUploadLengthExceeded() throws Exception {
+ tusFileUploadService.withMaxUploadSize(10L);
+
+ String uploadContent = "This is upload is too long";
+
+ // Create upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, uploadContent.getBytes().length);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ }
+
+ @Test
+ public void testInvalidMethods() throws Exception {
+ servletRequest.setMethod("PUT");
+ servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+
+ reset();
+ servletRequest.setMethod("CONNECT");
+ servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+
+ reset();
+ servletRequest.setMethod("TRACE");
+ servletRequest.setRequestURI(UPLOAD_URI + "/" + UUID.randomUUID());
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ }
+
+ protected void assertResponseHeader(final String header, final String value) {
+ assertThat(servletResponse.getHeader(header), is(value));
+ }
+
+ protected void assertResponseHeader(final String header, final String... values) {
+ assertThat(
+ Arrays.asList(servletResponse.getHeader(header).split(",")), containsInAnyOrder(values));
+ }
+
+ protected void assertResponseHeaderNotBlank(final String header) {
+ assertTrue(StringUtils.isNotBlank(servletResponse.getHeader(header)));
+ }
+
+ protected void assertResponseHeaderNull(final String header) {
+ assertTrue(servletResponse.getHeader(header) == null);
+ }
+
+ protected void assertResponseStatus(final int httpStatus) {
+ assertThat(servletResponse.getStatus(), is(httpStatus));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/ITTusFileUploadServiceCached.java b/src/test/java/me/desair/tus/server/ITTusFileUploadServiceCached.java
index 2166aa3..eede1d8 100644
--- a/src/test/java/me/desair/tus/server/ITTusFileUploadServiceCached.java
+++ b/src/test/java/me/desair/tus/server/ITTusFileUploadServiceCached.java
@@ -4,7 +4,6 @@
import static org.hamcrest.MatcherAssert.assertThat;
import jakarta.servlet.http.HttpServletResponse;
-
import me.desair.tus.server.upload.TimeBasedUploadIdFactory;
import me.desair.tus.server.upload.UploadLockingService;
import me.desair.tus.server.upload.UploadStorageService;
@@ -18,94 +17,95 @@
public class ITTusFileUploadServiceCached extends ITTusFileUploadService {
- @Override
- @Before
- public void setUp() {
- super.setUp();
- tusFileUploadService = tusFileUploadService
- .withThreadLocalCache(true)
- .withUploadIdFactory(new TimeBasedUploadIdFactory());
- }
-
- @Test
- public void testProcessUploadDoubleCached() throws Exception {
- String path = storagePath.toAbsolutePath().toString();
- UploadStorageService uploadStorageService = new DiskStorageService(path);
- UploadLockingService uploadLockingService = new DiskLockingService(path);
-
- ThreadLocalCachedStorageAndLockingService service2 =
- new ThreadLocalCachedStorageAndLockingService(
- uploadStorageService,
- uploadLockingService);
-
- service2.setUploadConcatenationService(new VirtualConcatenationService(service2));
-
- tusFileUploadService.withUploadStorageService(service2);
- tusFileUploadService.withUploadLockingService(service2);
-
- assertThat(service2.getUploadURI(), is(UPLOAD_URI));
- assertThat(uploadStorageService.getUploadURI(), is(UPLOAD_URI));
-
- testConcatenationCompleted();
- }
-
- @Test
- public void testCachedUploadDifferentKey() throws Exception {
- String uploadContent = "This is an upload of someone else";
-
- //Create upload
- servletRequest.setMethod("POST");
- servletRequest.setRequestURI(UPLOAD_URI);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, uploadContent.getBytes().length);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeaderNotBlank(HttpHeader.LOCATION);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- String location = UPLOAD_URI +
- StringUtils.substringAfter(servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
-
- //Upload bytes
- reset();
- servletRequest.setMethod("PATCH");
- servletRequest.setRequestURI(location);
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, uploadContent.getBytes().length);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- servletRequest.setContent(uploadContent.getBytes());
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + uploadContent.getBytes().length);
- assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
-
- //Download the upload to check content
- reset();
- servletRequest.setMethod("GET");
- servletRequest.setRequestURI(location);
-
- tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "" + uploadContent.getBytes().length);
- assertResponseStatus(HttpServletResponse.SC_OK);
- assertThat(servletResponse.getContentAsString(), is("This is an upload of someone else"));
-
- //Try to download the upload under a different key
- reset();
- servletRequest.setMethod("GET");
- servletRequest.setRequestURI(location);
-
- tusFileUploadService.process(servletRequest, servletResponse, "ALTER-EGO");
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
- assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
- }
+ @Override
+ @Before
+ public void setUp() {
+ super.setUp();
+ tusFileUploadService =
+ tusFileUploadService
+ .withThreadLocalCache(true)
+ .withUploadIdFactory(new TimeBasedUploadIdFactory());
+ }
+
+ @Test
+ public void testProcessUploadDoubleCached() throws Exception {
+ String path = storagePath.toAbsolutePath().toString();
+ UploadStorageService uploadStorageService = new DiskStorageService(path);
+ UploadLockingService uploadLockingService = new DiskLockingService(path);
+
+ ThreadLocalCachedStorageAndLockingService service2 =
+ new ThreadLocalCachedStorageAndLockingService(uploadStorageService, uploadLockingService);
+
+ service2.setUploadConcatenationService(new VirtualConcatenationService(service2));
+
+ tusFileUploadService.withUploadStorageService(service2);
+ tusFileUploadService.withUploadLockingService(service2);
+
+ assertThat(service2.getUploadURI(), is(UPLOAD_URI));
+ assertThat(uploadStorageService.getUploadURI(), is(UPLOAD_URI));
+
+ testConcatenationCompleted();
+ }
+
+ @Test
+ public void testCachedUploadDifferentKey() throws Exception {
+ String uploadContent = "This is an upload of someone else";
+
+ // Create upload
+ servletRequest.setMethod("POST");
+ servletRequest.setRequestURI(UPLOAD_URI);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, uploadContent.getBytes().length);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeaderNotBlank(HttpHeader.LOCATION);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ String location =
+ UPLOAD_URI
+ + StringUtils.substringAfter(
+ servletResponse.getHeader(HttpHeader.LOCATION), UPLOAD_URI);
+
+ // Upload bytes
+ reset();
+ servletRequest.setMethod("PATCH");
+ servletRequest.setRequestURI(location);
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/offset+octet-stream");
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, uploadContent.getBytes().length);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ servletRequest.setContent(uploadContent.getBytes());
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "" + uploadContent.getBytes().length);
+ assertResponseHeaderNotBlank(HttpHeader.UPLOAD_EXPIRES);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+
+ // Download the upload to check content
+ reset();
+ servletRequest.setMethod("GET");
+ servletRequest.setRequestURI(location);
+
+ tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY);
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "" + uploadContent.getBytes().length);
+ assertResponseStatus(HttpServletResponse.SC_OK);
+ assertThat(servletResponse.getContentAsString(), is("This is an upload of someone else"));
+
+ // Try to download the upload under a different key
+ reset();
+ servletRequest.setMethod("GET");
+ servletRequest.setRequestURI(location);
+
+ tusFileUploadService.process(servletRequest, servletResponse, "ALTER-EGO");
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.CONTENT_LENGTH, "0");
+ assertResponseStatus(HttpServletResponse.SC_NOT_FOUND);
+ }
}
diff --git a/src/test/java/me/desair/tus/server/checksum/ChecksumAlgorithmTest.java b/src/test/java/me/desair/tus/server/checksum/ChecksumAlgorithmTest.java
index ec12f70..c4dce87 100644
--- a/src/test/java/me/desair/tus/server/checksum/ChecksumAlgorithmTest.java
+++ b/src/test/java/me/desair/tus/server/checksum/ChecksumAlgorithmTest.java
@@ -7,41 +7,46 @@
public class ChecksumAlgorithmTest {
- @Test
- public void getMessageDigest() throws Exception {
- assertNotNull(ChecksumAlgorithm.MD5.getMessageDigest());
- assertNotNull(ChecksumAlgorithm.SHA1.getMessageDigest());
- assertNotNull(ChecksumAlgorithm.SHA256.getMessageDigest());
- assertNotNull(ChecksumAlgorithm.SHA384.getMessageDigest());
- assertNotNull(ChecksumAlgorithm.SHA512.getMessageDigest());
- }
+ @Test
+ public void getMessageDigest() throws Exception {
+ assertNotNull(ChecksumAlgorithm.MD5.getMessageDigest());
+ assertNotNull(ChecksumAlgorithm.SHA1.getMessageDigest());
+ assertNotNull(ChecksumAlgorithm.SHA256.getMessageDigest());
+ assertNotNull(ChecksumAlgorithm.SHA384.getMessageDigest());
+ assertNotNull(ChecksumAlgorithm.SHA512.getMessageDigest());
+ }
- @Test
- public void forTusName() throws Exception {
- assertEquals(ChecksumAlgorithm.MD5, ChecksumAlgorithm.forTusName("md5"));
- assertEquals(ChecksumAlgorithm.SHA1, ChecksumAlgorithm.forTusName("sha1"));
- assertEquals(ChecksumAlgorithm.SHA256, ChecksumAlgorithm.forTusName("sha256"));
- assertEquals(ChecksumAlgorithm.SHA384, ChecksumAlgorithm.forTusName("sha384"));
- assertEquals(ChecksumAlgorithm.SHA512, ChecksumAlgorithm.forTusName("sha512"));
- assertEquals(null, ChecksumAlgorithm.forTusName("test"));
- }
+ @Test
+ public void forTusName() throws Exception {
+ assertEquals(ChecksumAlgorithm.MD5, ChecksumAlgorithm.forTusName("md5"));
+ assertEquals(ChecksumAlgorithm.SHA1, ChecksumAlgorithm.forTusName("sha1"));
+ assertEquals(ChecksumAlgorithm.SHA256, ChecksumAlgorithm.forTusName("sha256"));
+ assertEquals(ChecksumAlgorithm.SHA384, ChecksumAlgorithm.forTusName("sha384"));
+ assertEquals(ChecksumAlgorithm.SHA512, ChecksumAlgorithm.forTusName("sha512"));
+ assertEquals(null, ChecksumAlgorithm.forTusName("test"));
+ }
- @Test
- public void forUploadChecksumHeader() throws Exception {
- assertEquals(ChecksumAlgorithm.MD5, ChecksumAlgorithm.forUploadChecksumHeader("md5 1234567890"));
- assertEquals(ChecksumAlgorithm.SHA1, ChecksumAlgorithm.forUploadChecksumHeader("sha1 1234567890"));
- assertEquals(ChecksumAlgorithm.SHA256, ChecksumAlgorithm.forUploadChecksumHeader("sha256 1234567890"));
- assertEquals(ChecksumAlgorithm.SHA384, ChecksumAlgorithm.forUploadChecksumHeader("sha384 1234567890"));
- assertEquals(ChecksumAlgorithm.SHA512, ChecksumAlgorithm.forUploadChecksumHeader("sha512 1234567890"));
- assertEquals(null, ChecksumAlgorithm.forUploadChecksumHeader("test 1234567890"));
- }
+ @Test
+ public void forUploadChecksumHeader() throws Exception {
+ assertEquals(
+ ChecksumAlgorithm.MD5, ChecksumAlgorithm.forUploadChecksumHeader("md5 1234567890"));
+ assertEquals(
+ ChecksumAlgorithm.SHA1, ChecksumAlgorithm.forUploadChecksumHeader("sha1 1234567890"));
+ assertEquals(
+ ChecksumAlgorithm.SHA256, ChecksumAlgorithm.forUploadChecksumHeader("sha256 1234567890"));
+ assertEquals(
+ ChecksumAlgorithm.SHA384, ChecksumAlgorithm.forUploadChecksumHeader("sha384 1234567890"));
+ assertEquals(
+ ChecksumAlgorithm.SHA512, ChecksumAlgorithm.forUploadChecksumHeader("sha512 1234567890"));
+ assertEquals(null, ChecksumAlgorithm.forUploadChecksumHeader("test 1234567890"));
+ }
- @Test
- public void testToString() throws Exception {
- assertEquals("md5", ChecksumAlgorithm.MD5.toString());
- assertEquals("sha1", ChecksumAlgorithm.SHA1.toString());
- assertEquals("sha256", ChecksumAlgorithm.SHA256.toString());
- assertEquals("sha384", ChecksumAlgorithm.SHA384.toString());
- assertEquals("sha512", ChecksumAlgorithm.SHA512.toString());
- }
-}
\ No newline at end of file
+ @Test
+ public void testToString() throws Exception {
+ assertEquals("md5", ChecksumAlgorithm.MD5.toString());
+ assertEquals("sha1", ChecksumAlgorithm.SHA1.toString());
+ assertEquals("sha256", ChecksumAlgorithm.SHA256.toString());
+ assertEquals("sha384", ChecksumAlgorithm.SHA384.toString());
+ assertEquals("sha512", ChecksumAlgorithm.SHA512.toString());
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/checksum/ChecksumOptionsRequestHandlerTest.java b/src/test/java/me/desair/tus/server/checksum/ChecksumOptionsRequestHandlerTest.java
index 84f7fbd..382e344 100644
--- a/src/test/java/me/desair/tus/server/checksum/ChecksumOptionsRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/checksum/ChecksumOptionsRequestHandlerTest.java
@@ -5,7 +5,6 @@
import static org.hamcrest.Matchers.containsInAnyOrder;
import java.util.Arrays;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.util.TusServletRequest;
@@ -17,42 +16,47 @@
public class ChecksumOptionsRequestHandlerTest {
- private ChecksumOptionsRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new ChecksumOptionsRequestHandler();
- }
-
- @Test
- public void processListExtensions() throws Exception {
-
- handler.process(HttpMethod.OPTIONS, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), null, null);
-
- assertThat(Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_EXTENSION).split(",")),
- containsInAnyOrder("checksum", "checksum-trailer"));
-
- assertThat(Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_CHECKSUM_ALGORITHM).split(",")),
- containsInAnyOrder("md5", "sha1", "sha256", "sha384", "sha512"));
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
-}
\ No newline at end of file
+ private ChecksumOptionsRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new ChecksumOptionsRequestHandler();
+ }
+
+ @Test
+ public void processListExtensions() throws Exception {
+
+ handler.process(
+ HttpMethod.OPTIONS,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ null,
+ null);
+
+ assertThat(
+ Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_EXTENSION).split(",")),
+ containsInAnyOrder("checksum", "checksum-trailer"));
+
+ assertThat(
+ Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_CHECKSUM_ALGORITHM).split(",")),
+ containsInAnyOrder("md5", "sha1", "sha256", "sha384", "sha512"));
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/checksum/ChecksumPatchRequestHandlerTest.java b/src/test/java/me/desair/tus/server/checksum/ChecksumPatchRequestHandlerTest.java
index a20d338..26bd543 100644
--- a/src/test/java/me/desair/tus/server/checksum/ChecksumPatchRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/checksum/ChecksumPatchRequestHandlerTest.java
@@ -26,72 +26,71 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class ChecksumPatchRequestHandlerTest {
- private ChecksumPatchRequestHandler handler;
-
- @Mock
- private TusServletRequest servletRequest;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() throws Exception {
- handler = new ChecksumPatchRequestHandler();
-
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(true));
- assertThat(handler.supports(null), is(false));
- }
-
- @Test
- public void testValidHeaderAndChecksum() throws Exception {
- when(servletRequest.getHeader(HttpHeader.UPLOAD_CHECKSUM)).thenReturn("sha1 1234567890");
- when(servletRequest.getCalculatedChecksum(ArgumentMatchers.any(ChecksumAlgorithm.class)))
- .thenReturn("1234567890");
- when(servletRequest.hasCalculatedChecksum()).thenReturn(true);
-
- handler.process(HttpMethod.PATCH, servletRequest, null, uploadStorageService, null);
-
- verify(servletRequest, times(1)).getCalculatedChecksum(any(ChecksumAlgorithm.class));
- }
-
- @Test(expected = UploadChecksumMismatchException.class)
- public void testValidHeaderAndInvalidChecksum() throws Exception {
- when(servletRequest.getHeader(HttpHeader.UPLOAD_CHECKSUM)).thenReturn("sha1 1234567890");
- when(servletRequest.getCalculatedChecksum(ArgumentMatchers.any(ChecksumAlgorithm.class)))
- .thenReturn("0123456789");
- when(servletRequest.hasCalculatedChecksum()).thenReturn(true);
-
- handler.process(HttpMethod.PATCH, servletRequest, null, uploadStorageService, null);
- }
-
- @Test
- public void testNoHeader() throws Exception {
- when(servletRequest.getHeader(HttpHeader.UPLOAD_CHECKSUM)).thenReturn(null);
-
- handler.process(HttpMethod.PATCH, servletRequest, null, uploadStorageService, null);
-
- verify(servletRequest, never()).getCalculatedChecksum(any(ChecksumAlgorithm.class));
- }
-
- @Test(expected = ChecksumAlgorithmNotSupportedException.class)
- public void testInvalidHeader() throws Exception {
- when(servletRequest.getHeader(HttpHeader.UPLOAD_CHECKSUM)).thenReturn("test 1234567890");
- when(servletRequest.hasCalculatedChecksum()).thenReturn(true);
-
- handler.process(HttpMethod.PATCH, servletRequest, null, uploadStorageService, null);
- }
-}
\ No newline at end of file
+ private ChecksumPatchRequestHandler handler;
+
+ @Mock private TusServletRequest servletRequest;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() throws Exception {
+ handler = new ChecksumPatchRequestHandler();
+
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(true));
+ assertThat(handler.supports(null), is(false));
+ }
+
+ @Test
+ public void testValidHeaderAndChecksum() throws Exception {
+ when(servletRequest.getHeader(HttpHeader.UPLOAD_CHECKSUM)).thenReturn("sha1 1234567890");
+ when(servletRequest.getCalculatedChecksum(ArgumentMatchers.any(ChecksumAlgorithm.class)))
+ .thenReturn("1234567890");
+ when(servletRequest.hasCalculatedChecksum()).thenReturn(true);
+
+ handler.process(HttpMethod.PATCH, servletRequest, null, uploadStorageService, null);
+
+ verify(servletRequest, times(1)).getCalculatedChecksum(any(ChecksumAlgorithm.class));
+ }
+
+ @Test(expected = UploadChecksumMismatchException.class)
+ public void testValidHeaderAndInvalidChecksum() throws Exception {
+ when(servletRequest.getHeader(HttpHeader.UPLOAD_CHECKSUM)).thenReturn("sha1 1234567890");
+ when(servletRequest.getCalculatedChecksum(ArgumentMatchers.any(ChecksumAlgorithm.class)))
+ .thenReturn("0123456789");
+ when(servletRequest.hasCalculatedChecksum()).thenReturn(true);
+
+ handler.process(HttpMethod.PATCH, servletRequest, null, uploadStorageService, null);
+ }
+
+ @Test
+ public void testNoHeader() throws Exception {
+ when(servletRequest.getHeader(HttpHeader.UPLOAD_CHECKSUM)).thenReturn(null);
+
+ handler.process(HttpMethod.PATCH, servletRequest, null, uploadStorageService, null);
+
+ verify(servletRequest, never()).getCalculatedChecksum(any(ChecksumAlgorithm.class));
+ }
+
+ @Test(expected = ChecksumAlgorithmNotSupportedException.class)
+ public void testInvalidHeader() throws Exception {
+ when(servletRequest.getHeader(HttpHeader.UPLOAD_CHECKSUM)).thenReturn("test 1234567890");
+ when(servletRequest.hasCalculatedChecksum()).thenReturn(true);
+
+ handler.process(HttpMethod.PATCH, servletRequest, null, uploadStorageService, null);
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/checksum/ITChecksumExtension.java b/src/test/java/me/desair/tus/server/checksum/ITChecksumExtension.java
index 46b6153..e99ad3f 100644
--- a/src/test/java/me/desair/tus/server/checksum/ITChecksumExtension.java
+++ b/src/test/java/me/desair/tus/server/checksum/ITChecksumExtension.java
@@ -17,104 +17,107 @@
public class ITChecksumExtension extends AbstractTusExtensionIntegrationTest {
- @Before
- public void setUp() throws Exception {
- servletRequest = spy(new MockHttpServletRequest());
- servletResponse = new MockHttpServletResponse();
- tusFeature = new ChecksumExtension();
- uploadInfo = null;
+ @Before
+ public void setUp() throws Exception {
+ servletRequest = spy(new MockHttpServletRequest());
+ servletResponse = new MockHttpServletResponse();
+ tusFeature = new ChecksumExtension();
+ uploadInfo = null;
+ }
+
+ @Test
+ public void testOptions() throws Exception {
+ setRequestHeaders();
+
+ executeCall(HttpMethod.OPTIONS, false);
+
+ assertResponseHeader(HttpHeader.TUS_EXTENSION, "checksum", "checksum-trailer");
+ assertResponseHeader(
+ HttpHeader.TUS_CHECKSUM_ALGORITHM, "md5", "sha1", "sha256", "sha384", "sha512");
+ }
+
+ @Test(expected = ChecksumAlgorithmNotSupportedException.class)
+ public void testInvalidAlgorithm() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "test 1234567890");
+ servletRequest.setContent("Test content".getBytes());
+
+ executeCall(HttpMethod.PATCH, false);
+ }
+
+ @Test
+ public void testValidChecksumTrailerHeader() throws Exception {
+ String content =
+ "8\r\n"
+ + "Mozilla \r\n"
+ + "A\r\n"
+ + "Developer \r\n"
+ + "7\r\n"
+ + "Network\r\n"
+ + "0\r\n"
+ + "Upload-Checksum: sha1 zYR9iS5Rya+WoH1fEyfKqqdPWWE=\r\n"
+ + "\r\n";
+
+ servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
+ servletRequest.setContent(content.getBytes());
+
+ try {
+ executeCall(HttpMethod.PATCH, true);
+ } catch (Exception ex) {
+ fail();
}
+ }
- @Test
- public void testOptions() throws Exception {
- setRequestHeaders();
+ @Test
+ public void testValidChecksumNormalHeader() throws Exception {
+ String content = "Mozilla Developer Network";
- executeCall(HttpMethod.OPTIONS, false);
+ servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "sha1 zYR9iS5Rya+WoH1fEyfKqqdPWWE=");
+ servletRequest.setContent(content.getBytes());
- assertResponseHeader(HttpHeader.TUS_EXTENSION, "checksum", "checksum-trailer");
- assertResponseHeader(HttpHeader.TUS_CHECKSUM_ALGORITHM, "md5", "sha1", "sha256", "sha384", "sha512");
- }
-
- @Test(expected = ChecksumAlgorithmNotSupportedException.class)
- public void testInvalidAlgorithm() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "test 1234567890");
- servletRequest.setContent("Test content".getBytes());
-
- executeCall(HttpMethod.PATCH, false);
- }
-
- @Test
- public void testValidChecksumTrailerHeader() throws Exception {
- String content = "8\r\n" +
- "Mozilla \r\n" +
- "A\r\n" +
- "Developer \r\n" +
- "7\r\n" +
- "Network\r\n" +
- "0\r\n" +
- "Upload-Checksum: sha1 zYR9iS5Rya+WoH1fEyfKqqdPWWE=\r\n" +
- "\r\n";
-
- servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
- servletRequest.setContent(content.getBytes());
-
- try {
- executeCall(HttpMethod.PATCH, true);
- } catch (Exception ex) {
- fail();
- }
- }
+ executeCall(HttpMethod.PATCH, true);
- @Test
- public void testValidChecksumNormalHeader() throws Exception {
- String content = "Mozilla Developer Network";
+ verify(servletRequest, atLeastOnce()).getHeader(HttpHeader.UPLOAD_CHECKSUM);
+ }
- servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "sha1 zYR9iS5Rya+WoH1fEyfKqqdPWWE=");
- servletRequest.setContent(content.getBytes());
+ @Test(expected = UploadChecksumMismatchException.class)
+ public void testInvalidChecksumTrailerHeader() throws Exception {
+ String content =
+ "8\r\n"
+ + "Mozilla \r\n"
+ + "A\r\n"
+ + "Developer \r\n"
+ + "7\r\n"
+ + "Network\r\n"
+ + "0\r\n"
+ + "Upload-Checksum: sha1 zYR9iS5Rya+WoH1fEyfKqqdPWW=\r\n"
+ + "\r\n";
- executeCall(HttpMethod.PATCH, true);
+ servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
+ servletRequest.setContent(content.getBytes());
- verify(servletRequest, atLeastOnce()).getHeader(HttpHeader.UPLOAD_CHECKSUM);
- }
+ executeCall(HttpMethod.PATCH, true);
+ }
- @Test(expected = UploadChecksumMismatchException.class)
- public void testInvalidChecksumTrailerHeader() throws Exception {
- String content = "8\r\n" +
- "Mozilla \r\n" +
- "A\r\n" +
- "Developer \r\n" +
- "7\r\n" +
- "Network\r\n" +
- "0\r\n" +
- "Upload-Checksum: sha1 zYR9iS5Rya+WoH1fEyfKqqdPWW=\r\n" +
- "\r\n";
-
- servletRequest.addHeader(HttpHeader.TRANSFER_ENCODING, "chunked");
- servletRequest.setContent(content.getBytes());
-
- executeCall(HttpMethod.PATCH, true);
- }
+ @Test(expected = UploadChecksumMismatchException.class)
+ public void testInvalidChecksumNormalHeader() throws Exception {
+ String content = "Mozilla Developer Network";
- @Test(expected = UploadChecksumMismatchException.class)
- public void testInvalidChecksumNormalHeader() throws Exception {
- String content = "Mozilla Developer Network";
+ servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "sha1 zYR9iS5Rya+WoH1fEyfKqqdPWW=");
+ servletRequest.setContent(content.getBytes());
- servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "sha1 zYR9iS5Rya+WoH1fEyfKqqdPWW=");
- servletRequest.setContent(content.getBytes());
-
- executeCall(HttpMethod.PATCH, true);
- }
+ executeCall(HttpMethod.PATCH, true);
+ }
- @Test
- public void testNoChecksum() throws Exception {
- String content = "Mozilla Developer Network";
+ @Test
+ public void testNoChecksum() throws Exception {
+ String content = "Mozilla Developer Network";
- servletRequest.setContent(content.getBytes());
+ servletRequest.setContent(content.getBytes());
- try {
- executeCall(HttpMethod.PATCH, true);
- } catch (Exception ex) {
- fail();
- }
+ try {
+ executeCall(HttpMethod.PATCH, true);
+ } catch (Exception ex) {
+ fail();
}
-}
\ No newline at end of file
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/checksum/validation/ChecksumAlgorithmValidatorTest.java b/src/test/java/me/desair/tus/server/checksum/validation/ChecksumAlgorithmValidatorTest.java
index 9c69a27..63f1dff 100644
--- a/src/test/java/me/desair/tus/server/checksum/validation/ChecksumAlgorithmValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/checksum/validation/ChecksumAlgorithmValidatorTest.java
@@ -21,56 +21,54 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class ChecksumAlgorithmValidatorTest {
- private ChecksumAlgorithmValidator validator;
-
- private MockHttpServletRequest servletRequest;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = spy(new MockHttpServletRequest());
- validator = new ChecksumAlgorithmValidator();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(false));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(true));
- assertThat(validator.supports(null), is(false));
- }
-
- @Test
- public void testValid() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "sha1 1234567890");
-
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
-
- verify(servletRequest, times(1)).getHeader(HttpHeader.UPLOAD_CHECKSUM);
+ private ChecksumAlgorithmValidator validator;
+
+ private MockHttpServletRequest servletRequest;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = spy(new MockHttpServletRequest());
+ validator = new ChecksumAlgorithmValidator();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(false));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(true));
+ assertThat(validator.supports(null), is(false));
+ }
+
+ @Test
+ public void testValid() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "sha1 1234567890");
+
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+
+ verify(servletRequest, times(1)).getHeader(HttpHeader.UPLOAD_CHECKSUM);
+ }
+
+ @Test
+ public void testNoHeader() throws Exception {
+ // servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, null);
+
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
+ }
- @Test
- public void testNoHeader() throws Exception {
- //servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, null);
-
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
- }
-
- @Test(expected = ChecksumAlgorithmNotSupportedException.class)
- public void testInvalidHeader() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "test 1234567890");
-
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- }
+ @Test(expected = ChecksumAlgorithmNotSupportedException.class)
+ public void testInvalidHeader() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_CHECKSUM, "test 1234567890");
-}
\ No newline at end of file
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/concatenation/ConcatenationHeadRequestHandlerTest.java b/src/test/java/me/desair/tus/server/concatenation/ConcatenationHeadRequestHandlerTest.java
index a64b3ec..cff0870 100644
--- a/src/test/java/me/desair/tus/server/concatenation/ConcatenationHeadRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/concatenation/ConcatenationHeadRequestHandlerTest.java
@@ -11,7 +11,6 @@
import static org.mockito.Mockito.when;
import java.util.UUID;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.upload.UploadId;
@@ -32,115 +31,129 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class ConcatenationHeadRequestHandlerTest {
- private ConcatenationHeadRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Mock
- private UploadConcatenationService concatenationService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new ConcatenationHeadRequestHandler();
- when(uploadStorageService.getUploadConcatenationService()).thenReturn(concatenationService);
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(true));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
- @Test
- public void testRegularUpload() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
- info1.setUploadConcatHeaderValue("Impossible");
- info1.setUploadType(UploadType.REGULAR);
-
- when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()),
- nullable(String.class))).thenReturn(info1);
- servletRequest.setRequestURI(info1.getId().toString());
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_CONCAT), is(nullValue()));
- }
-
- @Test
- public void testPartialUpload() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
- info1.setUploadConcatHeaderValue("partial");
- info1.setUploadType(UploadType.PARTIAL);
-
- when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()),
- nullable(String.class))).thenReturn(info1);
- servletRequest.setRequestURI(info1.getId().toString());
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_CONCAT), is("partial"));
- }
-
- @Test
- public void testConcatenatedUploadWithLength() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
- info1.setUploadConcatHeaderValue("final; 123 456");
- info1.setLength(10L);
- info1.setOffset(10L);
- info1.setUploadType(UploadType.CONCATENATED);
-
- when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()),
- nullable(String.class))).thenReturn(info1);
- servletRequest.setRequestURI(info1.getId().toString());
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_CONCAT), is("final; 123 456"));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_LENGTH), is("10"));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is("10"));
-
- verify(concatenationService, never()).merge(info1);
- }
-
- @Test
- public void testConcatenatedUploadWithoutLength() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
- info1.setUploadConcatHeaderValue("final; 123 456");
- info1.setLength(10L);
- info1.setOffset(8L);
- info1.setUploadType(UploadType.CONCATENATED);
-
- when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()),
- nullable(String.class))).thenReturn(info1);
- servletRequest.setRequestURI(info1.getId().toString());
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_CONCAT), is("final; 123 456"));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_LENGTH), is("10"));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is(nullValue()));
-
- verify(concatenationService, times(1)).merge(info1);
- }
-}
\ No newline at end of file
+ private ConcatenationHeadRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Mock private UploadConcatenationService concatenationService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new ConcatenationHeadRequestHandler();
+ when(uploadStorageService.getUploadConcatenationService()).thenReturn(concatenationService);
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(true));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+
+ @Test
+ public void testRegularUpload() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+ info1.setUploadConcatHeaderValue("Impossible");
+ info1.setUploadType(UploadType.REGULAR);
+
+ when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()), nullable(String.class)))
+ .thenReturn(info1);
+ servletRequest.setRequestURI(info1.getId().toString());
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_CONCAT), is(nullValue()));
+ }
+
+ @Test
+ public void testPartialUpload() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+ info1.setUploadConcatHeaderValue("partial");
+ info1.setUploadType(UploadType.PARTIAL);
+
+ when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()), nullable(String.class)))
+ .thenReturn(info1);
+ servletRequest.setRequestURI(info1.getId().toString());
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_CONCAT), is("partial"));
+ }
+
+ @Test
+ public void testConcatenatedUploadWithLength() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+ info1.setUploadConcatHeaderValue("final; 123 456");
+ info1.setLength(10L);
+ info1.setOffset(10L);
+ info1.setUploadType(UploadType.CONCATENATED);
+
+ when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()), nullable(String.class)))
+ .thenReturn(info1);
+ servletRequest.setRequestURI(info1.getId().toString());
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_CONCAT), is("final; 123 456"));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_LENGTH), is("10"));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is("10"));
+
+ verify(concatenationService, never()).merge(info1);
+ }
+
+ @Test
+ public void testConcatenatedUploadWithoutLength() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+ info1.setUploadConcatHeaderValue("final; 123 456");
+ info1.setLength(10L);
+ info1.setOffset(8L);
+ info1.setUploadType(UploadType.CONCATENATED);
+
+ when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()), nullable(String.class)))
+ .thenReturn(info1);
+ servletRequest.setRequestURI(info1.getId().toString());
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_CONCAT), is("final; 123 456"));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_LENGTH), is("10"));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is(nullValue()));
+
+ verify(concatenationService, times(1)).merge(info1);
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/concatenation/ConcatenationOptionsRequestHandlerTest.java b/src/test/java/me/desair/tus/server/concatenation/ConcatenationOptionsRequestHandlerTest.java
index 7de1e1a..c8c8933 100644
--- a/src/test/java/me/desair/tus/server/concatenation/ConcatenationOptionsRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/concatenation/ConcatenationOptionsRequestHandlerTest.java
@@ -5,7 +5,6 @@
import static org.hamcrest.Matchers.containsInAnyOrder;
import java.util.Arrays;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.util.TusServletRequest;
@@ -17,39 +16,43 @@
public class ConcatenationOptionsRequestHandlerTest {
- private ConcatenationOptionsRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new ConcatenationOptionsRequestHandler();
- }
-
- @Test
- public void processListExtensions() throws Exception {
-
- handler.process(HttpMethod.OPTIONS, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), null, null);
-
- assertThat(Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_EXTENSION).split(",")),
- containsInAnyOrder("concatenation", "concatenation-unfinished"));
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
-}
\ No newline at end of file
+ private ConcatenationOptionsRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new ConcatenationOptionsRequestHandler();
+ }
+
+ @Test
+ public void processListExtensions() throws Exception {
+
+ handler.process(
+ HttpMethod.OPTIONS,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ null,
+ null);
+
+ assertThat(
+ Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_EXTENSION).split(",")),
+ containsInAnyOrder("concatenation", "concatenation-unfinished"));
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/concatenation/ConcatenationPostRequestHandlerTest.java b/src/test/java/me/desair/tus/server/concatenation/ConcatenationPostRequestHandlerTest.java
index 622efd1..473f226 100644
--- a/src/test/java/me/desair/tus/server/concatenation/ConcatenationPostRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/concatenation/ConcatenationPostRequestHandlerTest.java
@@ -12,7 +12,6 @@
import static org.mockito.Mockito.when;
import java.util.UUID;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.upload.UploadId;
@@ -33,111 +32,128 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class ConcatenationPostRequestHandlerTest {
- private ConcatenationPostRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Mock
- private UploadConcatenationService concatenationService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new ConcatenationPostRequestHandler();
- when(uploadStorageService.getUploadConcatenationService()).thenReturn(concatenationService);
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(true));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
- @Test
- public void testRegularUpload() throws Exception {
- TusServletResponse response = new TusServletResponse(this.servletResponse);
-
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
-
- when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()),
- nullable(String.class))).thenReturn(info1);
- response.setHeader(HttpHeader.LOCATION, info1.getId().toString());
-
- handler.process(HttpMethod.POST, new TusServletRequest(servletRequest), response, uploadStorageService, null);
-
- assertThat(info1.getUploadType(), is(UploadType.REGULAR));
- assertThat(info1.getUploadConcatHeaderValue(), is(nullValue()));
-
- verify(uploadStorageService, times(1)).update(info1);
- verify(concatenationService, never()).merge(info1);
- }
-
- @Test
- public void testPartialUpload() throws Exception {
- TusServletResponse response = new TusServletResponse(this.servletResponse);
-
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
-
- when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()),
- nullable(String.class))).thenReturn(info1);
- response.setHeader(HttpHeader.LOCATION, info1.getId().toString());
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
-
- handler.process(HttpMethod.POST, new TusServletRequest(servletRequest), response, uploadStorageService, null);
-
- assertThat(info1.getUploadType(), is(UploadType.PARTIAL));
- assertThat(info1.getUploadConcatHeaderValue(), is("partial"));
-
- verify(uploadStorageService, times(1)).update(info1);
- verify(concatenationService, never()).merge(info1);
- }
-
- @Test
- public void testFinalUpload() throws Exception {
- TusServletResponse response = new TusServletResponse(this.servletResponse);
-
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
-
- when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()),
- nullable(String.class))).thenReturn(info1);
- response.setHeader(HttpHeader.LOCATION, info1.getId().toString());
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final; 123 456");
-
- handler.process(HttpMethod.POST, new TusServletRequest(servletRequest), response, uploadStorageService, null);
-
- assertThat(info1.getUploadType(), is(UploadType.CONCATENATED));
- assertThat(info1.getUploadConcatHeaderValue(), is("final; 123 456"));
-
- verify(uploadStorageService, times(1)).update(info1);
- verify(concatenationService, times(1)).merge(info1);
- }
-
- @Test
- public void testUploadNotFound() throws Exception {
- TusServletResponse response = new TusServletResponse(this.servletResponse);
-
- response.setHeader(HttpHeader.LOCATION, "/test/upload/1234");
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final; 123 456");
-
- handler.process(HttpMethod.POST, new TusServletRequest(servletRequest), response, uploadStorageService, null);
-
- verify(uploadStorageService, never()).update(any(UploadInfo.class));
- verify(concatenationService, never()).merge(any(UploadInfo.class));
- }
-
-}
\ No newline at end of file
+ private ConcatenationPostRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Mock private UploadConcatenationService concatenationService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new ConcatenationPostRequestHandler();
+ when(uploadStorageService.getUploadConcatenationService()).thenReturn(concatenationService);
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(true));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+
+ @Test
+ public void testRegularUpload() throws Exception {
+ TusServletResponse response = new TusServletResponse(this.servletResponse);
+
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+
+ when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()), nullable(String.class)))
+ .thenReturn(info1);
+ response.setHeader(HttpHeader.LOCATION, info1.getId().toString());
+
+ handler.process(
+ HttpMethod.POST,
+ new TusServletRequest(servletRequest),
+ response,
+ uploadStorageService,
+ null);
+
+ assertThat(info1.getUploadType(), is(UploadType.REGULAR));
+ assertThat(info1.getUploadConcatHeaderValue(), is(nullValue()));
+
+ verify(uploadStorageService, times(1)).update(info1);
+ verify(concatenationService, never()).merge(info1);
+ }
+
+ @Test
+ public void testPartialUpload() throws Exception {
+ TusServletResponse response = new TusServletResponse(this.servletResponse);
+
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+
+ when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()), nullable(String.class)))
+ .thenReturn(info1);
+ response.setHeader(HttpHeader.LOCATION, info1.getId().toString());
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
+
+ handler.process(
+ HttpMethod.POST,
+ new TusServletRequest(servletRequest),
+ response,
+ uploadStorageService,
+ null);
+
+ assertThat(info1.getUploadType(), is(UploadType.PARTIAL));
+ assertThat(info1.getUploadConcatHeaderValue(), is("partial"));
+
+ verify(uploadStorageService, times(1)).update(info1);
+ verify(concatenationService, never()).merge(info1);
+ }
+
+ @Test
+ public void testFinalUpload() throws Exception {
+ TusServletResponse response = new TusServletResponse(this.servletResponse);
+
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+
+ when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()), nullable(String.class)))
+ .thenReturn(info1);
+ response.setHeader(HttpHeader.LOCATION, info1.getId().toString());
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final; 123 456");
+
+ handler.process(
+ HttpMethod.POST,
+ new TusServletRequest(servletRequest),
+ response,
+ uploadStorageService,
+ null);
+
+ assertThat(info1.getUploadType(), is(UploadType.CONCATENATED));
+ assertThat(info1.getUploadConcatHeaderValue(), is("final; 123 456"));
+
+ verify(uploadStorageService, times(1)).update(info1);
+ verify(concatenationService, times(1)).merge(info1);
+ }
+
+ @Test
+ public void testUploadNotFound() throws Exception {
+ TusServletResponse response = new TusServletResponse(this.servletResponse);
+
+ response.setHeader(HttpHeader.LOCATION, "/test/upload/1234");
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final; 123 456");
+
+ handler.process(
+ HttpMethod.POST,
+ new TusServletRequest(servletRequest),
+ response,
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).update(any(UploadInfo.class));
+ verify(concatenationService, never()).merge(any(UploadInfo.class));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/concatenation/validation/NoUploadLengthOnFinalValidatorTest.java b/src/test/java/me/desair/tus/server/concatenation/validation/NoUploadLengthOnFinalValidatorTest.java
index 6248949..bfc6c97 100644
--- a/src/test/java/me/desair/tus/server/concatenation/validation/NoUploadLengthOnFinalValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/concatenation/validation/NoUploadLengthOnFinalValidatorTest.java
@@ -13,80 +13,79 @@
public class NoUploadLengthOnFinalValidatorTest {
- private NoUploadLengthOnFinalValidator validator;
-
- private MockHttpServletRequest servletRequest;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new NoUploadLengthOnFinalValidator();
+ private NoUploadLengthOnFinalValidator validator;
+
+ private MockHttpServletRequest servletRequest;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new NoUploadLengthOnFinalValidator();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(true));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(false));
+ assertThat(validator.supports(null), is(false));
+ }
+
+ @Test
+ public void validateFinalUploadValid() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final;12345 235235 253523");
+ // servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "10L");
+
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(true));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(false));
- assertThat(validator.supports(null), is(false));
- }
-
- @Test
- public void validateFinalUploadValid() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final;12345 235235 253523");
- //servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "10L");
-
- //When we validate the request
- try {
- validator.validate(HttpMethod.POST, servletRequest, null, null);
- } catch (Exception ex) {
- fail();
- }
+ // No Exception is thrown
+ }
- //No Exception is thrown
- }
-
- @Test(expected = UploadLengthNotAllowedOnConcatenationException.class)
- public void validateFinalUploadInvalid() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final;12345 235235 253523");
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "10L");
-
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, null, null);
- }
+ @Test(expected = UploadLengthNotAllowedOnConcatenationException.class)
+ public void validateFinalUploadInvalid() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final;12345 235235 253523");
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "10L");
- @Test
- public void validateNotFinal1() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "10L");
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
+ }
- //When we validate the request
- try {
- validator.validate(HttpMethod.POST, servletRequest, null, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateNotFinal1() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "10L");
- //No Exception is thrown
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateNotFinal2() throws Exception {
- //servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
- //servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "10L");
+ // No Exception is thrown
+ }
- //When we validate the request
- try {
- validator.validate(HttpMethod.POST, servletRequest, null, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateNotFinal2() throws Exception {
+ // servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "partial");
+ // servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "10L");
- //No Exception is thrown
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
+ } catch (Exception ex) {
+ fail();
}
-}
\ No newline at end of file
+ // No Exception is thrown
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/concatenation/validation/PartialUploadsExistValidatorTest.java b/src/test/java/me/desair/tus/server/concatenation/validation/PartialUploadsExistValidatorTest.java
index 1d23023..436d2d5 100644
--- a/src/test/java/me/desair/tus/server/concatenation/validation/PartialUploadsExistValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/concatenation/validation/PartialUploadsExistValidatorTest.java
@@ -5,7 +5,6 @@
import static org.mockito.Mockito.when;
import java.util.UUID;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.InvalidPartialUploadIdException;
@@ -22,94 +21,95 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class PartialUploadsExistValidatorTest {
- private PartialUploadsExistValidator validator;
+ private PartialUploadsExistValidator validator;
- private MockHttpServletRequest servletRequest;
+ private MockHttpServletRequest servletRequest;
- @Mock
- private UploadStorageService uploadStorageService;
+ @Mock private UploadStorageService uploadStorageService;
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new PartialUploadsExistValidator();
- }
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new PartialUploadsExistValidator();
+ }
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(true));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(false));
- assertThat(validator.supports(null), is(false));
- }
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(true));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(false));
+ assertThat(validator.supports(null), is(false));
+ }
- @Test
- public void testValid() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
+ @Test
+ public void testValid() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
- UploadInfo info2 = new UploadInfo();
- info2.setId(new UploadId(UUID.randomUUID()));
+ UploadInfo info2 = new UploadInfo();
+ info2.setId(new UploadId(UUID.randomUUID()));
- when(uploadStorageService.getUploadInfo(info1.getId().toString(), null)).thenReturn(info1);
- when(uploadStorageService.getUploadInfo(info2.getId().toString(), null)).thenReturn(info2);
+ when(uploadStorageService.getUploadInfo(info1.getId().toString(), null)).thenReturn(info1);
+ when(uploadStorageService.getUploadInfo(info2.getId().toString(), null)).thenReturn(info2);
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, String.format("final; %s %s", info1.getId(), info2.getId()));
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_CONCAT, String.format("final; %s %s", info1.getId(), info2.getId()));
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- //No exception is thrown
- }
+ // No exception is thrown
+ }
- @Test(expected = InvalidPartialUploadIdException.class)
- public void testInvalidUploadNotFound() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
+ @Test(expected = InvalidPartialUploadIdException.class)
+ public void testInvalidUploadNotFound() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
- when(uploadStorageService.getUploadInfo(info1.getId())).thenReturn(info1);
+ when(uploadStorageService.getUploadInfo(info1.getId())).thenReturn(info1);
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT,
- String.format("final; %s %s", info1.getId(), UUID.randomUUID()));
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_CONCAT, String.format("final; %s %s", info1.getId(), UUID.randomUUID()));
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- }
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ }
- @Test(expected = InvalidPartialUploadIdException.class)
- public void testInvalidId() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
+ @Test(expected = InvalidPartialUploadIdException.class)
+ public void testInvalidId() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
- when(uploadStorageService.getUploadInfo(info1.getId().toString(), null)).thenReturn(info1);
+ when(uploadStorageService.getUploadInfo(info1.getId().toString(), null)).thenReturn(info1);
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, String.format("final; %s %s", info1.getId(), "test"));
+ servletRequest.addHeader(
+ HttpHeader.UPLOAD_CONCAT, String.format("final; %s %s", info1.getId(), "test"));
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- }
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ }
- @Test(expected = InvalidPartialUploadIdException.class)
- public void testInvalidNoUploads1() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final; ");
+ @Test(expected = InvalidPartialUploadIdException.class)
+ public void testInvalidNoUploads1() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final; ");
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- //No Exception is thrown
- }
+ // No Exception is thrown
+ }
- @Test(expected = InvalidPartialUploadIdException.class)
- public void testInvalidNoUploads2() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final;");
+ @Test(expected = InvalidPartialUploadIdException.class)
+ public void testInvalidNoUploads2() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final;");
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- //No Exception is thrown
- }
-}
\ No newline at end of file
+ // No Exception is thrown
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/concatenation/validation/PatchFinalUploadValidatorTest.java b/src/test/java/me/desair/tus/server/concatenation/validation/PatchFinalUploadValidatorTest.java
index 6ba9d85..d04f6bc 100644
--- a/src/test/java/me/desair/tus/server/concatenation/validation/PatchFinalUploadValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/concatenation/validation/PatchFinalUploadValidatorTest.java
@@ -8,7 +8,6 @@
import static org.mockito.Mockito.when;
import java.util.UUID;
-
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.PatchOnFinalUploadNotAllowedException;
import me.desair.tus.server.upload.UploadId;
@@ -25,91 +24,90 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class PatchFinalUploadValidatorTest {
- private PatchFinalUploadValidator validator;
-
- private MockHttpServletRequest servletRequest;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new PatchFinalUploadValidator();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(false));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(true));
- assertThat(validator.supports(null), is(false));
+ private PatchFinalUploadValidator validator;
+
+ private MockHttpServletRequest servletRequest;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new PatchFinalUploadValidator();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(false));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(true));
+ assertThat(validator.supports(null), is(false));
+ }
+
+ @Test
+ public void testValid() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+ info1.setUploadType(UploadType.REGULAR);
+
+ UploadInfo info2 = new UploadInfo();
+ info2.setId(new UploadId(UUID.randomUUID()));
+ info2.setUploadType(UploadType.PARTIAL);
+
+ UploadInfo info3 = new UploadInfo();
+ info3.setId(new UploadId(UUID.randomUUID()));
+ info3.setUploadType(null);
+
+ when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()), nullable(String.class)))
+ .thenReturn(info1);
+ when(uploadStorageService.getUploadInfo(eq(info2.getId().toString()), nullable(String.class)))
+ .thenReturn(info2);
+ when(uploadStorageService.getUploadInfo(eq(info3.getId().toString()), nullable(String.class)))
+ .thenReturn(info3);
+
+ // When we validate the requests
+ try {
+ servletRequest.setRequestURI(info1.getId().toString());
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+
+ servletRequest.setRequestURI(info2.getId().toString());
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+
+ servletRequest.setRequestURI(info3.getId().toString());
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void testValid() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
- info1.setUploadType(UploadType.REGULAR);
-
- UploadInfo info2 = new UploadInfo();
- info2.setId(new UploadId(UUID.randomUUID()));
- info2.setUploadType(UploadType.PARTIAL);
-
- UploadInfo info3 = new UploadInfo();
- info3.setId(new UploadId(UUID.randomUUID()));
- info3.setUploadType(null);
-
- when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()),
- nullable(String.class))).thenReturn(info1);
- when(uploadStorageService.getUploadInfo(eq(info2.getId().toString()),
- nullable(String.class))).thenReturn(info2);
- when(uploadStorageService.getUploadInfo(eq(info3.getId().toString()),
- nullable(String.class))).thenReturn(info3);
-
- //When we validate the requests
- try {
- servletRequest.setRequestURI(info1.getId().toString());
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
-
- servletRequest.setRequestURI(info2.getId().toString());
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
-
- servletRequest.setRequestURI(info3.getId().toString());
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
-
- //No exception is thrown
- }
-
- @Test
- public void testValidNotFound() throws Exception {
- try {
- //When we validate the request
- servletRequest.setRequestURI("/upload/test");
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
- }
-
- @Test(expected = PatchOnFinalUploadNotAllowedException.class)
- public void testInvalidFinal() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
- info1.setUploadType(UploadType.CONCATENATED);
-
- when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()),
- nullable(String.class))).thenReturn(info1);
-
- //When we validate the request
- servletRequest.setRequestURI(info1.getId().toString());
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ // No exception is thrown
+ }
+
+ @Test
+ public void testValidNotFound() throws Exception {
+ try {
+ // When we validate the request
+ servletRequest.setRequestURI("/upload/test");
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
-}
\ No newline at end of file
+ }
+
+ @Test(expected = PatchOnFinalUploadNotAllowedException.class)
+ public void testInvalidFinal() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+ info1.setUploadType(UploadType.CONCATENATED);
+
+ when(uploadStorageService.getUploadInfo(eq(info1.getId().toString()), nullable(String.class)))
+ .thenReturn(info1);
+
+ // When we validate the request
+ servletRequest.setRequestURI(info1.getId().toString());
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/CoreDefaultResponseHeadersHandlerTest.java b/src/test/java/me/desair/tus/server/core/CoreDefaultResponseHeadersHandlerTest.java
index c762675..ccac155 100644
--- a/src/test/java/me/desair/tus/server/core/CoreDefaultResponseHeadersHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/core/CoreDefaultResponseHeadersHandlerTest.java
@@ -15,37 +15,43 @@
public class CoreDefaultResponseHeadersHandlerTest {
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- private CoreDefaultResponseHeadersHandler handler;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new CoreDefaultResponseHeadersHandler();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(true));
- assertThat(handler.supports(HttpMethod.POST), is(true));
- assertThat(handler.supports(HttpMethod.PUT), is(true));
- assertThat(handler.supports(HttpMethod.DELETE), is(true));
- assertThat(handler.supports(HttpMethod.HEAD), is(true));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
- assertThat(handler.supports(HttpMethod.PATCH), is(true));
- assertThat(handler.supports(null), is(true));
- }
-
- @Test
- public void process() throws Exception {
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), null, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.TUS_RESUMABLE), is(TusFileUploadService.TUS_API_VERSION));
- assertThat(servletResponse.getHeader(HttpHeader.CONTENT_LENGTH), is("0"));
- }
-}
\ No newline at end of file
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ private CoreDefaultResponseHeadersHandler handler;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new CoreDefaultResponseHeadersHandler();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(true));
+ assertThat(handler.supports(HttpMethod.POST), is(true));
+ assertThat(handler.supports(HttpMethod.PUT), is(true));
+ assertThat(handler.supports(HttpMethod.DELETE), is(true));
+ assertThat(handler.supports(HttpMethod.HEAD), is(true));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
+ assertThat(handler.supports(HttpMethod.PATCH), is(true));
+ assertThat(handler.supports(null), is(true));
+ }
+
+ @Test
+ public void process() throws Exception {
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ null,
+ null);
+
+ assertThat(
+ servletResponse.getHeader(HttpHeader.TUS_RESUMABLE),
+ is(TusFileUploadService.TUS_API_VERSION));
+ assertThat(servletResponse.getHeader(HttpHeader.CONTENT_LENGTH), is("0"));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/CoreHeadRequestHandlerTest.java b/src/test/java/me/desair/tus/server/core/CoreHeadRequestHandlerTest.java
index 84e827e..2316520 100644
--- a/src/test/java/me/desair/tus/server/core/CoreHeadRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/core/CoreHeadRequestHandlerTest.java
@@ -7,7 +7,6 @@
import static org.mockito.Mockito.when;
import jakarta.servlet.http.HttpServletResponse;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.upload.UploadInfo;
@@ -26,80 +25,93 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class CoreHeadRequestHandlerTest {
- private CoreHeadRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new CoreHeadRequestHandler();
- }
-
- @Test
- public void processWithLength() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_LENGTH), is("10"));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is("2"));
- assertThat(servletResponse.getHeader(HttpHeader.CACHE_CONTROL), is("no-store"));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
- }
-
- @Test
- public void processConcatenatedWithLength() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- info.setUploadType(UploadType.CONCATENATED);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_LENGTH), is(nullValue()));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is(nullValue()));
- assertThat(servletResponse.getHeader(HttpHeader.CACHE_CONTROL), is("no-store"));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
- }
-
- @Test
- public void processWithoutLength() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(0L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_LENGTH), is(nullValue()));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is("0"));
- assertThat(servletResponse.getHeader(HttpHeader.CACHE_CONTROL), is("no-store"));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(true));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
-}
\ No newline at end of file
+ private CoreHeadRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new CoreHeadRequestHandler();
+ }
+
+ @Test
+ public void processWithLength() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_LENGTH), is("10"));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is("2"));
+ assertThat(servletResponse.getHeader(HttpHeader.CACHE_CONTROL), is("no-store"));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
+ }
+
+ @Test
+ public void processConcatenatedWithLength() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ info.setUploadType(UploadType.CONCATENATED);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_LENGTH), is(nullValue()));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is(nullValue()));
+ assertThat(servletResponse.getHeader(HttpHeader.CACHE_CONTROL), is("no-store"));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
+ }
+
+ @Test
+ public void processWithoutLength() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(0L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_LENGTH), is(nullValue()));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is("0"));
+ assertThat(servletResponse.getHeader(HttpHeader.CACHE_CONTROL), is("no-store"));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(true));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/CoreOptionsRequestHandlerTest.java b/src/test/java/me/desair/tus/server/core/CoreOptionsRequestHandlerTest.java
index d89754c..8873e57 100644
--- a/src/test/java/me/desair/tus/server/core/CoreOptionsRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/core/CoreOptionsRequestHandlerTest.java
@@ -6,7 +6,6 @@
import static org.mockito.Mockito.when;
import jakarta.servlet.http.HttpServletResponse;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.TusFileUploadService;
@@ -24,56 +23,64 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class CoreOptionsRequestHandlerTest {
- private CoreOptionsRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new CoreOptionsRequestHandler();
- }
-
- @Test
- public void processWithMaxSize() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(5368709120L);
-
- handler.process(HttpMethod.OPTIONS, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.TUS_VERSION), is(TusFileUploadService.TUS_API_VERSION));
- assertThat(servletResponse.getHeader(HttpHeader.TUS_MAX_SIZE), is("5368709120"));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
- }
-
- @Test
- public void processWithoutMaxSize() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(0L);
-
- handler.process(HttpMethod.OPTIONS, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.TUS_VERSION), is("1.0.0"));
- assertThat(servletResponse.getHeader(HttpHeader.TUS_MAX_SIZE), is(nullValue()));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
-}
\ No newline at end of file
+ private CoreOptionsRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new CoreOptionsRequestHandler();
+ }
+
+ @Test
+ public void processWithMaxSize() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(5368709120L);
+
+ handler.process(
+ HttpMethod.OPTIONS,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(
+ servletResponse.getHeader(HttpHeader.TUS_VERSION),
+ is(TusFileUploadService.TUS_API_VERSION));
+ assertThat(servletResponse.getHeader(HttpHeader.TUS_MAX_SIZE), is("5368709120"));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
+ }
+
+ @Test
+ public void processWithoutMaxSize() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(0L);
+
+ handler.process(
+ HttpMethod.OPTIONS,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.TUS_VERSION), is("1.0.0"));
+ assertThat(servletResponse.getHeader(HttpHeader.TUS_MAX_SIZE), is(nullValue()));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/CorePatchRequestHandlerTest.java b/src/test/java/me/desair/tus/server/core/CorePatchRequestHandlerTest.java
index b8c4ae8..99db90b 100644
--- a/src/test/java/me/desair/tus/server/core/CorePatchRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/core/CorePatchRequestHandlerTest.java
@@ -10,10 +10,9 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import jakarta.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.UUID;
-import jakarta.servlet.http.HttpServletResponse;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.UploadNotFoundException;
@@ -33,100 +32,119 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class CorePatchRequestHandlerTest {
- private CorePatchRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new CorePatchRequestHandler();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(true));
- assertThat(handler.supports(null), is(false));
- }
-
- @Test
- public void processInProgress() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setId(new UploadId(UUID.randomUUID()));
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- UploadInfo updatedInfo = new UploadInfo();
- updatedInfo.setId(info.getId());
- updatedInfo.setOffset(8L);
- updatedInfo.setLength(10L);
- when(uploadStorageService.append(any(UploadInfo.class), any(InputStream.class))).thenReturn(updatedInfo);
-
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
-
- verify(uploadStorageService, times(1)).append(eq(info), any(InputStream.class));
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is("8"));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
- }
-
- @Test
- public void processFinished() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setId(new UploadId(UUID.randomUUID()));
- info.setOffset(10L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, never()).append(any(UploadInfo.class), any(InputStream.class));
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is("10"));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
- }
-
- @Test
- public void processNotFound() throws Exception {
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(null);
-
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, never()).append(any(UploadInfo.class), any(InputStream.class));
-
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
- }
-
- @Test
- public void processAppendNotFound() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setId(new UploadId(UUID.randomUUID()));
- info.setOffset(10L);
- info.setLength(8L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
- when(uploadStorageService.append(any(UploadInfo.class), any(InputStream.class)))
- .thenThrow(new UploadNotFoundException("test"));
-
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
- }
-}
\ No newline at end of file
+ private CorePatchRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new CorePatchRequestHandler();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(true));
+ assertThat(handler.supports(null), is(false));
+ }
+
+ @Test
+ public void processInProgress() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setId(new UploadId(UUID.randomUUID()));
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ UploadInfo updatedInfo = new UploadInfo();
+ updatedInfo.setId(info.getId());
+ updatedInfo.setOffset(8L);
+ updatedInfo.setLength(10L);
+ when(uploadStorageService.append(any(UploadInfo.class), any(InputStream.class)))
+ .thenReturn(updatedInfo);
+
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1)).append(eq(info), any(InputStream.class));
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is("8"));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
+ }
+
+ @Test
+ public void processFinished() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setId(new UploadId(UUID.randomUUID()));
+ info.setOffset(10L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).append(any(UploadInfo.class), any(InputStream.class));
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_OFFSET), is("10"));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
+ }
+
+ @Test
+ public void processNotFound() throws Exception {
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(null);
+
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).append(any(UploadInfo.class), any(InputStream.class));
+
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
+ }
+
+ @Test
+ public void processAppendNotFound() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setId(new UploadId(UUID.randomUUID()));
+ info.setOffset(10L);
+ info.setLength(8L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+ when(uploadStorageService.append(any(UploadInfo.class), any(InputStream.class)))
+ .thenThrow(new UploadNotFoundException("test"));
+
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/ITCoreProtocol.java b/src/test/java/me/desair/tus/server/core/ITCoreProtocol.java
index 0febcdb..8cf26a7 100644
--- a/src/test/java/me/desair/tus/server/core/ITCoreProtocol.java
+++ b/src/test/java/me/desair/tus/server/core/ITCoreProtocol.java
@@ -7,9 +7,8 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.io.InputStream;
import jakarta.servlet.http.HttpServletResponse;
-
+import java.io.InputStream;
import me.desair.tus.server.AbstractTusExtensionIntegrationTest;
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
@@ -27,160 +26,162 @@
public class ITCoreProtocol extends AbstractTusExtensionIntegrationTest {
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- tusFeature = new CoreProtocol();
- uploadInfo = null;
- }
-
- @Test
- public void getName() throws Exception {
- assertThat(tusFeature.getName(), is("core"));
- }
-
- @Test(expected = UnsupportedMethodException.class)
- public void testUnsupportedHttpMethod() throws Exception {
- prepareUploadInfo(2L, 10L);
- setRequestHeaders(HttpHeader.TUS_RESUMABLE);
-
- executeCall(HttpMethod.forName("TEST"), false);
- }
-
- @Test
- public void testHeadWithLength() throws Exception {
- prepareUploadInfo(2L, 10L);
- setRequestHeaders(HttpHeader.TUS_RESUMABLE);
-
- executeCall(HttpMethod.HEAD, false);
-
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "2");
- assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "10");
- assertResponseHeader(HttpHeader.CACHE_CONTROL, "no-store");
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- }
-
- @Test
- public void testHeadWithoutLength() throws Exception {
- prepareUploadInfo(2L, null);
- setRequestHeaders(HttpHeader.TUS_RESUMABLE);
-
- executeCall(HttpMethod.HEAD, false);
-
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "2");
- assertResponseHeader(HttpHeader.UPLOAD_LENGTH, (String) null);
- assertResponseHeader(HttpHeader.CACHE_CONTROL, "no-store");
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- }
-
- @Test(expected = UploadNotFoundException.class)
- public void testHeadNotFound() throws Exception {
- //We don't prepare an upload info
- setRequestHeaders(HttpHeader.TUS_RESUMABLE);
-
- executeCall(HttpMethod.HEAD, false);
- }
-
- @Test(expected = InvalidTusResumableException.class)
- public void testHeadInvalidVersion() throws Exception {
- setRequestHeaders();
- prepareUploadInfo(2L, null);
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "2.0.0");
-
- executeCall(HttpMethod.HEAD, false);
- }
-
- @Test
- public void testPatchSuccess() throws Exception {
- prepareUploadInfo(2L, 10L);
- setRequestHeaders(HttpHeader.TUS_RESUMABLE, HttpHeader.CONTENT_TYPE, HttpHeader.UPLOAD_OFFSET,
- HttpHeader.CONTENT_LENGTH);
-
- executeCall(HttpMethod.PATCH, false);
-
- verify(uploadStorageService, times(1))
- .append(any(UploadInfo.class), any(InputStream.class));
-
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "2");
- assertResponseHeader(HttpHeader.UPLOAD_LENGTH, (String) null);
- assertResponseHeader(HttpHeader.CACHE_CONTROL, (String) null);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- }
-
- @Test(expected = InvalidContentTypeException.class)
- public void testPatchInvalidContentType() throws Exception {
- prepareUploadInfo(2L, 10L);
- setRequestHeaders(HttpHeader.TUS_RESUMABLE, HttpHeader.UPLOAD_OFFSET, HttpHeader.CONTENT_LENGTH);
-
- executeCall(HttpMethod.PATCH, false);
- }
-
- @Test(expected = UploadOffsetMismatchException.class)
- public void testPatchInvalidUploadOffset() throws Exception {
- prepareUploadInfo(2L, 10L);
- setRequestHeaders(HttpHeader.TUS_RESUMABLE, HttpHeader.CONTENT_TYPE, HttpHeader.CONTENT_LENGTH);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 5);
-
- executeCall(HttpMethod.PATCH, false);
- }
-
- @Test(expected = InvalidContentLengthException.class)
- public void testPatchInvalidContentLength() throws Exception {
- prepareUploadInfo(2L, 10L);
- setRequestHeaders(HttpHeader.TUS_RESUMABLE, HttpHeader.CONTENT_TYPE, HttpHeader.UPLOAD_OFFSET);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 9);
-
- executeCall(HttpMethod.PATCH, false);
- }
-
- @Test
- public void testOptionsWithMaxSize() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(107374182400L);
-
- setRequestHeaders();
-
- executeCall(HttpMethod.OPTIONS, false);
-
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.TUS_VERSION, "1.0.0");
- assertResponseHeader(HttpHeader.TUS_MAX_SIZE, "107374182400");
- assertResponseHeader(HttpHeader.TUS_EXTENSION, (String) null);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- }
-
- @Test
- public void testOptionsWithNoMaxSize() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(0L);
-
- setRequestHeaders();
-
- executeCall(HttpMethod.OPTIONS, false);
-
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.TUS_VERSION, "1.0.0");
- assertResponseHeader(HttpHeader.TUS_MAX_SIZE, (String) null);
- assertResponseHeader(HttpHeader.TUS_EXTENSION, (String) null);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- }
-
-
- @Test
- public void testOptionsIgnoreTusResumable() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(10L);
-
- setRequestHeaders();
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "2.0.0");
-
- executeCall(HttpMethod.OPTIONS, false);
-
- assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- assertResponseHeader(HttpHeader.TUS_VERSION, "1.0.0");
- assertResponseHeader(HttpHeader.TUS_MAX_SIZE, "10");
- assertResponseHeader(HttpHeader.TUS_EXTENSION, (String) null);
- assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
- }
-}
\ No newline at end of file
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ tusFeature = new CoreProtocol();
+ uploadInfo = null;
+ }
+
+ @Test
+ public void getName() throws Exception {
+ assertThat(tusFeature.getName(), is("core"));
+ }
+
+ @Test(expected = UnsupportedMethodException.class)
+ public void testUnsupportedHttpMethod() throws Exception {
+ prepareUploadInfo(2L, 10L);
+ setRequestHeaders(HttpHeader.TUS_RESUMABLE);
+
+ executeCall(HttpMethod.forName("TEST"), false);
+ }
+
+ @Test
+ public void testHeadWithLength() throws Exception {
+ prepareUploadInfo(2L, 10L);
+ setRequestHeaders(HttpHeader.TUS_RESUMABLE);
+
+ executeCall(HttpMethod.HEAD, false);
+
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "2");
+ assertResponseHeader(HttpHeader.UPLOAD_LENGTH, "10");
+ assertResponseHeader(HttpHeader.CACHE_CONTROL, "no-store");
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ }
+
+ @Test
+ public void testHeadWithoutLength() throws Exception {
+ prepareUploadInfo(2L, null);
+ setRequestHeaders(HttpHeader.TUS_RESUMABLE);
+
+ executeCall(HttpMethod.HEAD, false);
+
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "2");
+ assertResponseHeader(HttpHeader.UPLOAD_LENGTH, (String) null);
+ assertResponseHeader(HttpHeader.CACHE_CONTROL, "no-store");
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ }
+
+ @Test(expected = UploadNotFoundException.class)
+ public void testHeadNotFound() throws Exception {
+ // We don't prepare an upload info
+ setRequestHeaders(HttpHeader.TUS_RESUMABLE);
+
+ executeCall(HttpMethod.HEAD, false);
+ }
+
+ @Test(expected = InvalidTusResumableException.class)
+ public void testHeadInvalidVersion() throws Exception {
+ setRequestHeaders();
+ prepareUploadInfo(2L, null);
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "2.0.0");
+
+ executeCall(HttpMethod.HEAD, false);
+ }
+
+ @Test
+ public void testPatchSuccess() throws Exception {
+ prepareUploadInfo(2L, 10L);
+ setRequestHeaders(
+ HttpHeader.TUS_RESUMABLE,
+ HttpHeader.CONTENT_TYPE,
+ HttpHeader.UPLOAD_OFFSET,
+ HttpHeader.CONTENT_LENGTH);
+
+ executeCall(HttpMethod.PATCH, false);
+
+ verify(uploadStorageService, times(1)).append(any(UploadInfo.class), any(InputStream.class));
+
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.UPLOAD_OFFSET, "2");
+ assertResponseHeader(HttpHeader.UPLOAD_LENGTH, (String) null);
+ assertResponseHeader(HttpHeader.CACHE_CONTROL, (String) null);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ }
+
+ @Test(expected = InvalidContentTypeException.class)
+ public void testPatchInvalidContentType() throws Exception {
+ prepareUploadInfo(2L, 10L);
+ setRequestHeaders(
+ HttpHeader.TUS_RESUMABLE, HttpHeader.UPLOAD_OFFSET, HttpHeader.CONTENT_LENGTH);
+
+ executeCall(HttpMethod.PATCH, false);
+ }
+
+ @Test(expected = UploadOffsetMismatchException.class)
+ public void testPatchInvalidUploadOffset() throws Exception {
+ prepareUploadInfo(2L, 10L);
+ setRequestHeaders(HttpHeader.TUS_RESUMABLE, HttpHeader.CONTENT_TYPE, HttpHeader.CONTENT_LENGTH);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 5);
+
+ executeCall(HttpMethod.PATCH, false);
+ }
+
+ @Test(expected = InvalidContentLengthException.class)
+ public void testPatchInvalidContentLength() throws Exception {
+ prepareUploadInfo(2L, 10L);
+ setRequestHeaders(HttpHeader.TUS_RESUMABLE, HttpHeader.CONTENT_TYPE, HttpHeader.UPLOAD_OFFSET);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 9);
+
+ executeCall(HttpMethod.PATCH, false);
+ }
+
+ @Test
+ public void testOptionsWithMaxSize() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(107374182400L);
+
+ setRequestHeaders();
+
+ executeCall(HttpMethod.OPTIONS, false);
+
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.TUS_VERSION, "1.0.0");
+ assertResponseHeader(HttpHeader.TUS_MAX_SIZE, "107374182400");
+ assertResponseHeader(HttpHeader.TUS_EXTENSION, (String) null);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ }
+
+ @Test
+ public void testOptionsWithNoMaxSize() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(0L);
+
+ setRequestHeaders();
+
+ executeCall(HttpMethod.OPTIONS, false);
+
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.TUS_VERSION, "1.0.0");
+ assertResponseHeader(HttpHeader.TUS_MAX_SIZE, (String) null);
+ assertResponseHeader(HttpHeader.TUS_EXTENSION, (String) null);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ }
+
+ @Test
+ public void testOptionsIgnoreTusResumable() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(10L);
+
+ setRequestHeaders();
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "2.0.0");
+
+ executeCall(HttpMethod.OPTIONS, false);
+
+ assertResponseHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ assertResponseHeader(HttpHeader.TUS_VERSION, "1.0.0");
+ assertResponseHeader(HttpHeader.TUS_MAX_SIZE, "10");
+ assertResponseHeader(HttpHeader.TUS_EXTENSION, (String) null);
+ assertResponseStatus(HttpServletResponse.SC_NO_CONTENT);
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/validation/ContentLengthValidatorTest.java b/src/test/java/me/desair/tus/server/core/validation/ContentLengthValidatorTest.java
index 442f7db..7dd347d 100644
--- a/src/test/java/me/desair/tus/server/core/validation/ContentLengthValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/core/validation/ContentLengthValidatorTest.java
@@ -21,167 +21,173 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class ContentLengthValidatorTest {
- private ContentLengthValidator validator;
+ private ContentLengthValidator validator;
- private MockHttpServletRequest servletRequest;
+ private MockHttpServletRequest servletRequest;
- @Mock
- private UploadStorageService uploadStorageService;
+ @Mock private UploadStorageService uploadStorageService;
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new ContentLengthValidator();
- }
-
- @Test
- public void validateValidLengthInitialUpload() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(0L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 10L);
-
- //When we validate the request
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
-
- //No Exception is thrown
- }
-
- @Test
- public void validateValidLengthInProgressUpload() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(5L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 5L);
-
- //When we validate the request
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
-
- //No Exception is thrown
- }
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new ContentLengthValidator();
+ }
- @Test
- public void validateValidLengthPartialUpload() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
+ @Test
+ public void validateValidLengthInitialUpload() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(0L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 3L);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 10L);
- //When we validate the request
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
-
- //No Exception is thrown
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test(expected = InvalidContentLengthException.class)
- public void validateInvalidLengthInitialUpload() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(0L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
+ // No Exception is thrown
+ }
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 11L);
+ @Test
+ public void validateValidLengthInProgressUpload() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(5L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
- //When we validate the request
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 5L);
- //Then expect a InvalidContentLengthException exception
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test(expected = InvalidContentLengthException.class)
- public void validateInvalidLengthInProgressUpload() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(5L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
+ // No Exception is thrown
+ }
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 6L);
+ @Test
+ public void validateValidLengthPartialUpload() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
- //When we validate the request
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 3L);
- //Then expect a InvalidContentLengthException exception
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test(expected = InvalidContentLengthException.class)
- public void validateInvalidLengthPartialUpload() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 10L);
-
- //When we validate the request
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
-
- //Then expect a InvalidContentLengthException exception
+ // No Exception is thrown
+ }
+
+ @Test(expected = InvalidContentLengthException.class)
+ public void validateInvalidLengthInitialUpload() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(0L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 11L);
+
+ // When we validate the request
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+
+ // Then expect a InvalidContentLengthException exception
+ }
+
+ @Test(expected = InvalidContentLengthException.class)
+ public void validateInvalidLengthInProgressUpload() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(5L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 6L);
+
+ // When we validate the request
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+
+ // Then expect a InvalidContentLengthException exception
+ }
+
+ @Test(expected = InvalidContentLengthException.class)
+ public void validateInvalidLengthPartialUpload() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 10L);
+
+ // When we validate the request
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+
+ // Then expect a InvalidContentLengthException exception
+ }
+
+ @Test
+ public void validateMissingContentLength() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ // We don't set a content length header
+ // servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 3L);
+
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateMissingContentLength() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- //We don't set a content length header
- //servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 3L);
+ // No Exception is thrown
+ }
- //When we validate the request
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateMissingUploadInfo() throws Exception {
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(null);
- //No Exception is thrown
- }
-
- @Test
- public void validateMissingUploadInfo() throws Exception {
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(null);
-
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 3L);
-
- //When we validate the request
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
-
- //No Exception is thrown
- }
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 3L);
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(false));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(true));
- assertThat(validator.supports(null), is(false));
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
-}
\ No newline at end of file
+ // No Exception is thrown
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(false));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(true));
+ assertThat(validator.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/validation/ContentTypeValidatorTest.java b/src/test/java/me/desair/tus/server/core/validation/ContentTypeValidatorTest.java
index 09e6167..8053088 100644
--- a/src/test/java/me/desair/tus/server/core/validation/ContentTypeValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/core/validation/ContentTypeValidatorTest.java
@@ -11,61 +11,61 @@
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
-
public class ContentTypeValidatorTest {
- private ContentTypeValidator validator;
-
- private MockHttpServletRequest servletRequest;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new ContentTypeValidator();
- }
+ private ContentTypeValidator validator;
- @Test
- public void validateValid() throws Exception {
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, ContentTypeValidator.APPLICATION_OFFSET_OCTET_STREAM);
-
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, null, null);
- } catch (Exception ex) {
- fail();
- }
-
- //No exception is thrown
- }
+ private MockHttpServletRequest servletRequest;
- @Test(expected = InvalidContentTypeException.class)
- public void validateInvalidHeader() throws Exception {
- servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/octet-stream");
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new ContentTypeValidator();
+ }
- validator.validate(HttpMethod.PATCH, servletRequest, null, null);
-
- //Expect a InvalidContentTypeException exception
- }
-
- @Test(expected = InvalidContentTypeException.class)
- public void validateMissingHeader() throws Exception {
- //We don't set the header
- //servletRequest.addHeader(HttpHeader.CONTENT_TYPE, ContentTypeValidator.APPLICATION_OFFSET_OCTET_STREAM);
-
- validator.validate(HttpMethod.PATCH, servletRequest, null, null);
-
- //Expect a InvalidContentTypeException exception
- }
+ @Test
+ public void validateValid() throws Exception {
+ servletRequest.addHeader(
+ HttpHeader.CONTENT_TYPE, ContentTypeValidator.APPLICATION_OFFSET_OCTET_STREAM);
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(false));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(true));
- assertThat(validator.supports(null), is(false));
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, null, null);
+ } catch (Exception ex) {
+ fail();
}
-}
\ No newline at end of file
+ // No exception is thrown
+ }
+
+ @Test(expected = InvalidContentTypeException.class)
+ public void validateInvalidHeader() throws Exception {
+ servletRequest.addHeader(HttpHeader.CONTENT_TYPE, "application/octet-stream");
+
+ validator.validate(HttpMethod.PATCH, servletRequest, null, null);
+
+ // Expect a InvalidContentTypeException exception
+ }
+
+ @Test(expected = InvalidContentTypeException.class)
+ public void validateMissingHeader() throws Exception {
+ // We don't set the header
+ // servletRequest.addHeader(HttpHeader.CONTENT_TYPE,
+ // ContentTypeValidator.APPLICATION_OFFSET_OCTET_STREAM);
+
+ validator.validate(HttpMethod.PATCH, servletRequest, null, null);
+
+ // Expect a InvalidContentTypeException exception
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(false));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(true));
+ assertThat(validator.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/validation/HttpMethodValidatorTest.java b/src/test/java/me/desair/tus/server/core/validation/HttpMethodValidatorTest.java
index 8a509ca..b305e0e 100644
--- a/src/test/java/me/desair/tus/server/core/validation/HttpMethodValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/core/validation/HttpMethodValidatorTest.java
@@ -14,40 +14,40 @@
public class HttpMethodValidatorTest {
- private MockHttpServletRequest servletRequest;
- private HttpMethodValidator validator;
- private UploadStorageService uploadStorageService;
- private UploadIdFactory idFactory;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new HttpMethodValidator();
+ private MockHttpServletRequest servletRequest;
+ private HttpMethodValidator validator;
+ private UploadStorageService uploadStorageService;
+ private UploadIdFactory idFactory;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new HttpMethodValidator();
+ }
+
+ @Test
+ public void validateValid() throws Exception {
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
-
- @Test
- public void validateValid() throws Exception {
- try {
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
- }
-
- @Test(expected = UnsupportedMethodException.class)
- public void validateInvalid() throws Exception {
- validator.validate(null, servletRequest, uploadStorageService, null);
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(true));
- assertThat(validator.supports(HttpMethod.POST), is(true));
- assertThat(validator.supports(HttpMethod.PUT), is(true));
- assertThat(validator.supports(HttpMethod.DELETE), is(true));
- assertThat(validator.supports(HttpMethod.HEAD), is(true));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(true));
- assertThat(validator.supports(HttpMethod.PATCH), is(true));
- assertThat(validator.supports(null), is(true));
- }
-}
\ No newline at end of file
+ }
+
+ @Test(expected = UnsupportedMethodException.class)
+ public void validateInvalid() throws Exception {
+ validator.validate(null, servletRequest, uploadStorageService, null);
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(true));
+ assertThat(validator.supports(HttpMethod.POST), is(true));
+ assertThat(validator.supports(HttpMethod.PUT), is(true));
+ assertThat(validator.supports(HttpMethod.DELETE), is(true));
+ assertThat(validator.supports(HttpMethod.HEAD), is(true));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(true));
+ assertThat(validator.supports(HttpMethod.PATCH), is(true));
+ assertThat(validator.supports(null), is(true));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/validation/IdExistsValidatorTest.java b/src/test/java/me/desair/tus/server/core/validation/IdExistsValidatorTest.java
index 0c5abe0..569c38a 100644
--- a/src/test/java/me/desair/tus/server/core/validation/IdExistsValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/core/validation/IdExistsValidatorTest.java
@@ -20,56 +20,56 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class IdExistsValidatorTest {
- private IdExistsValidator validator;
+ private IdExistsValidator validator;
- private MockHttpServletRequest servletRequest;
+ private MockHttpServletRequest servletRequest;
- @Mock
- private UploadStorageService uploadStorageService;
+ @Mock private UploadStorageService uploadStorageService;
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new IdExistsValidator();
- }
-
- @Test
- public void validateValid() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(0L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new IdExistsValidator();
+ }
- //When we validate the request
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateValid() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(0L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
- //No Exception is thrown
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test(expected = UploadNotFoundException.class)
- public void validateInvalid() throws Exception {
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(null);
+ // No Exception is thrown
+ }
- //When we validate the request
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ @Test(expected = UploadNotFoundException.class)
+ public void validateInvalid() throws Exception {
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(null);
- //Expect a UploadNotFoundException
- }
+ // When we validate the request
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(true));
- assertThat(validator.supports(HttpMethod.POST), is(false));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(true));
- assertThat(validator.supports(HttpMethod.HEAD), is(true));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(true));
- assertThat(validator.supports(null), is(false));
- }
+ // Expect a UploadNotFoundException
+ }
-}
\ No newline at end of file
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(true));
+ assertThat(validator.supports(HttpMethod.POST), is(false));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(true));
+ assertThat(validator.supports(HttpMethod.HEAD), is(true));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(true));
+ assertThat(validator.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/validation/TusResumableValidatorTest.java b/src/test/java/me/desair/tus/server/core/validation/TusResumableValidatorTest.java
index 9610e0a..7983999 100644
--- a/src/test/java/me/desair/tus/server/core/validation/TusResumableValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/core/validation/TusResumableValidatorTest.java
@@ -14,56 +14,56 @@
public class TusResumableValidatorTest {
- private MockHttpServletRequest servletRequest;
- private TusResumableValidator validator;
- private UploadStorageService uploadStorageService;
+ private MockHttpServletRequest servletRequest;
+ private TusResumableValidator validator;
+ private UploadStorageService uploadStorageService;
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new TusResumableValidator();
- }
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new TusResumableValidator();
+ }
- @Test(expected = InvalidTusResumableException.class)
- public void validateNoVersion() throws Exception {
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- }
+ @Test(expected = InvalidTusResumableException.class)
+ public void validateNoVersion() throws Exception {
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ }
- @Test(expected = InvalidTusResumableException.class)
- public void validateInvalidVersion() throws Exception {
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "2.0.0");
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- }
+ @Test(expected = InvalidTusResumableException.class)
+ public void validateInvalidVersion() throws Exception {
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "2.0.0");
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ }
- @Test
- public void validateValid() throws Exception {
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- try {
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateValid() throws Exception {
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
+ }
- @Test
- public void validateNullMethod() throws Exception {
- servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
- try {
- validator.validate(null, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateNullMethod() throws Exception {
+ servletRequest.addHeader(HttpHeader.TUS_RESUMABLE, "1.0.0");
+ try {
+ validator.validate(null, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
+ }
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(true));
- assertThat(validator.supports(HttpMethod.PUT), is(true));
- assertThat(validator.supports(HttpMethod.DELETE), is(true));
- assertThat(validator.supports(HttpMethod.HEAD), is(true));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(true));
- assertThat(validator.supports(null), is(true));
- }
-}
\ No newline at end of file
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(true));
+ assertThat(validator.supports(HttpMethod.PUT), is(true));
+ assertThat(validator.supports(HttpMethod.DELETE), is(true));
+ assertThat(validator.supports(HttpMethod.HEAD), is(true));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(true));
+ assertThat(validator.supports(null), is(true));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/core/validation/UploadOffsetValidatorTest.java b/src/test/java/me/desair/tus/server/core/validation/UploadOffsetValidatorTest.java
index c807940..f5815d2 100644
--- a/src/test/java/me/desair/tus/server/core/validation/UploadOffsetValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/core/validation/UploadOffsetValidatorTest.java
@@ -21,129 +21,133 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class UploadOffsetValidatorTest {
- private UploadOffsetValidator validator;
+ private UploadOffsetValidator validator;
- private MockHttpServletRequest servletRequest;
+ private MockHttpServletRequest servletRequest;
- @Mock
- private UploadStorageService uploadStorageService;
+ @Mock private UploadStorageService uploadStorageService;
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new UploadOffsetValidator();
- }
-
- @Test
- public void validateValidOffsetInitialUpload() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(0L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new UploadOffsetValidator();
+ }
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0L);
+ @Test
+ public void validateValidOffsetInitialUpload() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(0L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
- //When we validate the request
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 0L);
- //No Exception is thrown
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateValidOffsetInProgressUpload() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(5L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
+ // No Exception is thrown
+ }
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 5L);
+ @Test
+ public void validateValidOffsetInProgressUpload() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(5L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
- //When we validate the request
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 5L);
- //No Exception is thrown
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test(expected = UploadOffsetMismatchException.class)
- public void validateInvalidOffsetInitialUpload() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(0L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
+ // No Exception is thrown
+ }
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 3L);
+ @Test(expected = UploadOffsetMismatchException.class)
+ public void validateInvalidOffsetInitialUpload() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(0L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
- //When we validate the request
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 3L);
- //Then expect a UploadOffsetMismatchException exception
- }
+ // When we validate the request
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- @Test(expected = UploadOffsetMismatchException.class)
- public void validateInvalidOffsetInProgressUpload() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(5L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
+ // Then expect a UploadOffsetMismatchException exception
+ }
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 6L);
+ @Test(expected = UploadOffsetMismatchException.class)
+ public void validateInvalidOffsetInProgressUpload() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(5L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
- //When we validate the request
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 6L);
- //Then expect a UploadOffsetMismatchException exception
- }
+ // When we validate the request
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- @Test(expected = UploadOffsetMismatchException.class)
- public void validateMissingUploadOffset() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
+ // Then expect a UploadOffsetMismatchException exception
+ }
- //We don't set a content length header
- //servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 3L);
+ @Test(expected = UploadOffsetMismatchException.class)
+ public void validateMissingUploadOffset() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
- //When we validate the request
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ // We don't set a content length header
+ // servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 3L);
- //Then expect a UploadOffsetMismatchException exception
- }
-
- @Test
- public void validateMissingUploadInfo() throws Exception {
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(null);
+ // When we validate the request
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 3L);
+ // Then expect a UploadOffsetMismatchException exception
+ }
- //When we validate the request
- try {
- validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateMissingUploadInfo() throws Exception {
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(null);
- //No Exception is thrown
- }
+ servletRequest.addHeader(HttpHeader.UPLOAD_OFFSET, 3L);
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(false));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(true));
- assertThat(validator.supports(null), is(false));
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.PATCH, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
-}
\ No newline at end of file
+ // No Exception is thrown
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(false));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(true));
+ assertThat(validator.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/creation/CreationHeadRequestHandlerTest.java b/src/test/java/me/desair/tus/server/creation/CreationHeadRequestHandlerTest.java
index cc2c5d5..1ed367d 100644
--- a/src/test/java/me/desair/tus/server/creation/CreationHeadRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/creation/CreationHeadRequestHandlerTest.java
@@ -23,91 +23,110 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class CreationHeadRequestHandlerTest {
- private CreationHeadRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new CreationHeadRequestHandler();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(true));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
- @Test
- public void processWithLengthAndMetadata() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- info.setEncodedMetadata("encoded-metadata");
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is("encoded-metadata"));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
- }
-
- @Test
- public void processWithLengthAndNoMetadata() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- info.setEncodedMetadata(null);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
- }
-
- @Test
- public void processWithNoLengthAndMetadata() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(null);
- info.setEncodedMetadata("encoded-metadata");
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is("encoded-metadata"));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is("1"));
- }
-
- @Test
- public void processWithNoLengthAndNoMetadata() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(null);
- info.setEncodedMetadata(null);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is("1"));
- }
-}
\ No newline at end of file
+ private CreationHeadRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new CreationHeadRequestHandler();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(true));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+
+ @Test
+ public void processWithLengthAndMetadata() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ info.setEncodedMetadata("encoded-metadata");
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is("encoded-metadata"));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
+ }
+
+ @Test
+ public void processWithLengthAndNoMetadata() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ info.setEncodedMetadata(null);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
+ }
+
+ @Test
+ public void processWithNoLengthAndMetadata() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(null);
+ info.setEncodedMetadata("encoded-metadata");
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is("encoded-metadata"));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is("1"));
+ }
+
+ @Test
+ public void processWithNoLengthAndNoMetadata() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(null);
+ info.setEncodedMetadata(null);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is("1"));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/creation/CreationOptionsRequestHandlerTest.java b/src/test/java/me/desair/tus/server/creation/CreationOptionsRequestHandlerTest.java
index 14eb754..4476595 100644
--- a/src/test/java/me/desair/tus/server/creation/CreationOptionsRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/creation/CreationOptionsRequestHandlerTest.java
@@ -5,7 +5,6 @@
import static org.hamcrest.Matchers.containsInAnyOrder;
import java.util.Arrays;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.util.TusServletRequest;
@@ -17,39 +16,43 @@
public class CreationOptionsRequestHandlerTest {
- private CreationOptionsRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new CreationOptionsRequestHandler();
- }
-
- @Test
- public void processListExtensions() throws Exception {
-
- handler.process(HttpMethod.OPTIONS, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), null, null);
-
- assertThat(Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_EXTENSION).split(",")),
- containsInAnyOrder("creation", "creation-defer-length"));
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
-}
\ No newline at end of file
+ private CreationOptionsRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new CreationOptionsRequestHandler();
+ }
+
+ @Test
+ public void processListExtensions() throws Exception {
+
+ handler.process(
+ HttpMethod.OPTIONS,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ null,
+ null);
+
+ assertThat(
+ Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_EXTENSION).split(",")),
+ containsInAnyOrder("creation", "creation-defer-length"));
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/creation/CreationPatchRequestHandlerTest.java b/src/test/java/me/desair/tus/server/creation/CreationPatchRequestHandlerTest.java
index 2490a0b..be1f912 100644
--- a/src/test/java/me/desair/tus/server/creation/CreationPatchRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/creation/CreationPatchRequestHandlerTest.java
@@ -10,9 +10,8 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.util.UUID;
import jakarta.servlet.http.HttpServletResponse;
-
+import java.util.UUID;
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.UploadNotFoundException;
@@ -32,118 +31,148 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class CreationPatchRequestHandlerTest {
- private CreationPatchRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new CreationPatchRequestHandler();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(true));
- assertThat(handler.supports(null), is(false));
- }
-
-
- @Test
- public void processWithLengthAndHeader() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, never()).update(info);
- }
-
- @Test
- public void processWithLengthAndNoHeader() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- //servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, never()).update(info);
- }
-
- @Test
- public void processWithoutLengthAndHeader() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(null);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, times(1)).update(info);
- assertThat(info.getLength(), is(10L));
- }
-
- @Test
- public void processWithoutLengthAndNoHeader() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setOffset(2L);
- info.setLength(null);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- //servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
-
- handler.process(HttpMethod.HEAD, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, never()).update(info);
- }
-
- @Test
- public void processNotFound() throws Exception {
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(null);
-
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
- }
-
- @Test
- public void processAppendNotFound() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setId(new UploadId(UUID.randomUUID()));
- info.setOffset(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
-
- doThrow(new UploadNotFoundException("test")).when(uploadStorageService).update(any(UploadInfo.class));
-
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
- }
-}
\ No newline at end of file
+ private CreationPatchRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new CreationPatchRequestHandler();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(true));
+ assertThat(handler.supports(null), is(false));
+ }
+
+ @Test
+ public void processWithLengthAndHeader() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).update(info);
+ }
+
+ @Test
+ public void processWithLengthAndNoHeader() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ // servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).update(info);
+ }
+
+ @Test
+ public void processWithoutLengthAndHeader() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(null);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1)).update(info);
+ assertThat(info.getLength(), is(10L));
+ }
+
+ @Test
+ public void processWithoutLengthAndNoHeader() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setOffset(2L);
+ info.setLength(null);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ // servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
+
+ handler.process(
+ HttpMethod.HEAD,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).update(info);
+ }
+
+ @Test
+ public void processNotFound() throws Exception {
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(null);
+
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+ }
+
+ @Test
+ public void processAppendNotFound() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setId(new UploadId(UUID.randomUUID()));
+ info.setOffset(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
+
+ doThrow(new UploadNotFoundException("test"))
+ .when(uploadStorageService)
+ .update(any(UploadInfo.class));
+
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/creation/CreationPostRequestHandlerTest.java b/src/test/java/me/desair/tus/server/creation/CreationPostRequestHandlerTest.java
index 0ff35e0..0e28bb9 100644
--- a/src/test/java/me/desair/tus/server/creation/CreationPostRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/creation/CreationPostRequestHandlerTest.java
@@ -9,9 +9,8 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.util.UUID;
import jakarta.servlet.http.HttpServletResponse;
-
+import java.util.UUID;
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.upload.UploadId;
@@ -31,157 +30,185 @@
import org.springframework.mock.web.MockHttpServletResponse;
/**
- * The Server MUST acknowledge a successful upload creation with the 201 Created status.
- * The Server MUST set the Location header to the URL of the created resource. This URL MAY be absolute or relative.
+ * The Server MUST acknowledge a successful upload creation with the 201 Created status. The Server
+ * MUST set the Location header to the URL of the created resource. This URL MAY be absolute or
+ * relative.
*/
@RunWith(MockitoJUnitRunner.Silent.class)
public class CreationPostRequestHandlerTest {
- private CreationPostRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new CreationPostRequestHandler();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(true));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
- @Test
- public void processWithLengthAndMetadata() throws Exception {
- servletRequest.setRequestURI("/test/upload");
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "encoded-metadata");
-
- final UploadId id = new UploadId(UUID.randomUUID());
- when(uploadStorageService.create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class))).then(
- new Answer() {
- @Override
- public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
- UploadInfo upload = invocation.getArgument(0);
- assertThat(upload.getLength(), is(10L));
- assertThat(upload.getEncodedMetadata(), is("encoded-metadata"));
-
- upload.setId(id);
-
- return upload;
- }
- });
-
- handler.process(HttpMethod.POST, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, times(1)).create(ArgumentMatchers.any(UploadInfo.class),
- nullable(String.class));
- assertThat(servletResponse.getHeader(HttpHeader.LOCATION), endsWith("/test/upload/" + id.toString()));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_CREATED));
- }
-
- @Test
- public void processWithLengthAndNoMetadata() throws Exception {
- servletRequest.setRequestURI("/test/upload");
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
- //servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, null);
-
- final UploadId id = new UploadId(UUID.randomUUID());
- when(uploadStorageService.create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class))).then(
- new Answer() {
- @Override
- public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
- UploadInfo upload = invocation.getArgument(0);
- assertThat(upload.getLength(), is(10L));
- assertThat(upload.getEncodedMetadata(), is(nullValue()));
-
- upload.setId(id);
-
- return upload;
- }
- });
-
- handler.process(HttpMethod.POST, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, times(1)).create(ArgumentMatchers.any(UploadInfo.class),
- nullable(String.class));
- assertThat(servletResponse.getHeader(HttpHeader.LOCATION), endsWith("/test/upload/" + id.toString()));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_CREATED));
- }
-
- @Test
- public void processWithNoLengthAndMetadata() throws Exception {
- servletRequest.setRequestURI("/test/upload");
- //servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, null);
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "encoded-metadata");
-
- final UploadId id = new UploadId(UUID.randomUUID());
- when(uploadStorageService.create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class))).then(
- new Answer() {
- @Override
- public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
- UploadInfo upload = invocation.getArgument(0);
- assertThat(upload.getLength(), is(nullValue()));
- assertThat(upload.getEncodedMetadata(), is("encoded-metadata"));
-
- upload.setId(id);
-
- return upload;
- }
- });
-
- handler.process(HttpMethod.POST, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, times(1)).create(ArgumentMatchers.any(UploadInfo.class),
- nullable(String.class));
- assertThat(servletResponse.getHeader(HttpHeader.LOCATION), endsWith("/test/upload/" + id.toString()));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_CREATED));
- }
-
- @Test
- public void processWithNoLengthAndNoMetadata() throws Exception {
- servletRequest.setRequestURI("/test/upload");
- //servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, null);
- //servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, null);
-
- final UploadId id = new UploadId(UUID.randomUUID());
- when(uploadStorageService.create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class))).then(
- new Answer() {
- @Override
- public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
- UploadInfo upload = invocation.getArgument(0);
- assertThat(upload.getLength(), is(nullValue()));
- assertThat(upload.getEncodedMetadata(), is(nullValue()));
-
- upload.setId(id);
-
- return upload;
- }
- });
-
- handler.process(HttpMethod.POST, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, times(1)).create(ArgumentMatchers.any(UploadInfo.class),
- nullable(String.class));
- assertThat(servletResponse.getHeader(HttpHeader.LOCATION), endsWith("/test/upload/" + id.toString()));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_CREATED));
- }
-}
\ No newline at end of file
+ private CreationPostRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new CreationPostRequestHandler();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(true));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+
+ @Test
+ public void processWithLengthAndMetadata() throws Exception {
+ servletRequest.setRequestURI("/test/upload");
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
+ servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "encoded-metadata");
+
+ final UploadId id = new UploadId(UUID.randomUUID());
+ when(uploadStorageService.create(
+ ArgumentMatchers.any(UploadInfo.class), nullable(String.class)))
+ .then(
+ new Answer() {
+ @Override
+ public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
+ UploadInfo upload = invocation.getArgument(0);
+ assertThat(upload.getLength(), is(10L));
+ assertThat(upload.getEncodedMetadata(), is("encoded-metadata"));
+
+ upload.setId(id);
+
+ return upload;
+ }
+ });
+
+ handler.process(
+ HttpMethod.POST,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1))
+ .create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class));
+ assertThat(
+ servletResponse.getHeader(HttpHeader.LOCATION), endsWith("/test/upload/" + id.toString()));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_CREATED));
+ }
+
+ @Test
+ public void processWithLengthAndNoMetadata() throws Exception {
+ servletRequest.setRequestURI("/test/upload");
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 10L);
+ // servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, null);
+
+ final UploadId id = new UploadId(UUID.randomUUID());
+ when(uploadStorageService.create(
+ ArgumentMatchers.any(UploadInfo.class), nullable(String.class)))
+ .then(
+ new Answer() {
+ @Override
+ public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
+ UploadInfo upload = invocation.getArgument(0);
+ assertThat(upload.getLength(), is(10L));
+ assertThat(upload.getEncodedMetadata(), is(nullValue()));
+
+ upload.setId(id);
+
+ return upload;
+ }
+ });
+
+ handler.process(
+ HttpMethod.POST,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1))
+ .create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class));
+ assertThat(
+ servletResponse.getHeader(HttpHeader.LOCATION), endsWith("/test/upload/" + id.toString()));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_CREATED));
+ }
+
+ @Test
+ public void processWithNoLengthAndMetadata() throws Exception {
+ servletRequest.setRequestURI("/test/upload");
+ // servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, null);
+ servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "encoded-metadata");
+
+ final UploadId id = new UploadId(UUID.randomUUID());
+ when(uploadStorageService.create(
+ ArgumentMatchers.any(UploadInfo.class), nullable(String.class)))
+ .then(
+ new Answer() {
+ @Override
+ public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
+ UploadInfo upload = invocation.getArgument(0);
+ assertThat(upload.getLength(), is(nullValue()));
+ assertThat(upload.getEncodedMetadata(), is("encoded-metadata"));
+
+ upload.setId(id);
+
+ return upload;
+ }
+ });
+
+ handler.process(
+ HttpMethod.POST,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1))
+ .create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class));
+ assertThat(
+ servletResponse.getHeader(HttpHeader.LOCATION), endsWith("/test/upload/" + id.toString()));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_CREATED));
+ }
+
+ @Test
+ public void processWithNoLengthAndNoMetadata() throws Exception {
+ servletRequest.setRequestURI("/test/upload");
+ // servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, null);
+ // servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, null);
+
+ final UploadId id = new UploadId(UUID.randomUUID());
+ when(uploadStorageService.create(
+ ArgumentMatchers.any(UploadInfo.class), nullable(String.class)))
+ .then(
+ new Answer() {
+ @Override
+ public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
+ UploadInfo upload = invocation.getArgument(0);
+ assertThat(upload.getLength(), is(nullValue()));
+ assertThat(upload.getEncodedMetadata(), is(nullValue()));
+
+ upload.setId(id);
+
+ return upload;
+ }
+ });
+
+ handler.process(
+ HttpMethod.POST,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1))
+ .create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class));
+ assertThat(
+ servletResponse.getHeader(HttpHeader.LOCATION), endsWith("/test/upload/" + id.toString()));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_CREATED));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/creation/ITCreationExtension.java b/src/test/java/me/desair/tus/server/creation/ITCreationExtension.java
index f5d4a4e..2991deb 100644
--- a/src/test/java/me/desair/tus/server/creation/ITCreationExtension.java
+++ b/src/test/java/me/desair/tus/server/creation/ITCreationExtension.java
@@ -9,9 +9,8 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.util.UUID;
import jakarta.servlet.http.HttpServletResponse;
-
+import java.util.UUID;
import me.desair.tus.server.AbstractTusExtensionIntegrationTest;
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
@@ -30,243 +29,253 @@
public class ITCreationExtension extends AbstractTusExtensionIntegrationTest {
- private static final String UPLOAD_URI = "/test/upload";
-
- //It's important to return relative UPLOAD URLs in the Location header in order to support HTTPS proxies
- //that sit in front of the web app
- private static final String UPLOAD_URL = UPLOAD_URI + "/";
-
- private UploadId id;
-
- @Before
- public void setUp() throws Exception {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- tusFeature = new CreationExtension();
- uploadInfo = null;
-
- id = new UploadId(UUID.randomUUID());
- servletRequest.setRequestURI(UPLOAD_URI);
- reset(uploadStorageService);
- when(uploadStorageService.getUploadURI()).thenReturn(UPLOAD_URI);
- when(uploadStorageService.create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class))).then(
- new Answer() {
- @Override
- public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
- UploadInfo upload = invocation.getArgument(0);
- upload.setId(id);
-
- when(uploadStorageService.getUploadInfo(UPLOAD_URL + id.toString(),
- (String) invocation.getArgument(1))).thenReturn(upload);
- return upload;
- }
- });
- }
-
- @Test
- public void testOptions() throws Exception {
- setRequestHeaders();
-
- executeCall(HttpMethod.OPTIONS, false);
-
- //If the Server supports this extension, it MUST add creation to the Tus-Extension header.
- //If the Server supports deferring length, it MUST add creation-defer-length to the Tus-Extension header.
- assertResponseHeader(HttpHeader.TUS_EXTENSION, "creation", "creation-defer-length");
- }
-
- @Test
- public void testPostWithLength() throws Exception {
- //Create upload
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
-
- executeCall(HttpMethod.POST, false);
-
- verify(uploadStorageService, times(1)).create(any(UploadInfo.class),
- nullable(String.class));
- assertResponseHeader(HttpHeader.LOCATION, UPLOAD_URL + id.toString());
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- //Check data with head request
- servletRequest.setRequestURI(UPLOAD_URL + id.toString());
- servletResponse = new MockHttpServletResponse();
- executeCall(HttpMethod.HEAD, false);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
-
- //Test Patch request
- servletRequest = new MockHttpServletRequest();
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
- servletRequest.setRequestURI(UPLOAD_URL + id.toString());
- servletResponse = new MockHttpServletResponse();
- executeCall(HttpMethod.PATCH, false);
- }
-
- @Test
- public void testPostWithDeferredLength() throws Exception {
- //Create upload
- servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
-
- executeCall(HttpMethod.POST, false);
-
- verify(uploadStorageService, times(1)).create(any(UploadInfo.class),
- nullable(String.class));
- assertResponseHeader(HttpHeader.LOCATION, UPLOAD_URL + id.toString());
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- //Check data with head request
- servletRequest.setRequestURI(UPLOAD_URL + id.toString());
- servletResponse = new MockHttpServletResponse();
- executeCall(HttpMethod.HEAD, false);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is("1"));
-
- //Test Patch request
- servletRequest = new MockHttpServletRequest();
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
- servletRequest.setRequestURI(UPLOAD_URL + id.toString());
- servletResponse = new MockHttpServletResponse();
- executeCall(HttpMethod.PATCH, false);
-
- //Re-check head request
- servletRequest = new MockHttpServletRequest();
- servletRequest.setRequestURI(UPLOAD_URL + id.toString());
- servletResponse = new MockHttpServletResponse();
- executeCall(HttpMethod.HEAD, false);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
- }
-
- @Test(expected = InvalidUploadLengthException.class)
- public void testPostWithoutLength() throws Exception {
- //Create upload without any length header
- executeCall(HttpMethod.POST, false);
- }
-
- @Test
- public void testPostWithMetadata() throws Exception {
- //Create upload
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "encoded metadata");
-
- executeCall(HttpMethod.POST, false);
-
- verify(uploadStorageService, times(1)).create(any(UploadInfo.class),
- nullable(String.class));
- assertResponseHeader(HttpHeader.LOCATION, UPLOAD_URL + id.toString());
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- //Check data with head request
- servletRequest.setRequestURI(UPLOAD_URL + id.toString());
- servletResponse = new MockHttpServletResponse();
- executeCall(HttpMethod.HEAD, false);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is("encoded metadata"));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
- }
-
- @Test
- public void testPostWithAllowedMaxSize() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(100L);
-
- //Create upload
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 90);
- executeCall(HttpMethod.POST, false);
-
- verify(uploadStorageService, times(1)).create(any(UploadInfo.class),
- nullable(String.class));
- assertResponseHeader(HttpHeader.LOCATION, UPLOAD_URL + id.toString());
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- //Check data with head request
- servletRequest.setRequestURI(UPLOAD_URL + id.toString());
- servletResponse = new MockHttpServletResponse();
- executeCall(HttpMethod.HEAD, false);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
- }
-
- @Test(expected = MaxUploadLengthExceededException.class)
- public void testPostWithExceededMaxSize() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(100L);
-
- //Create upload
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 110);
- executeCall(HttpMethod.POST, false);
- }
-
- @Test(expected = PostOnInvalidRequestURIException.class)
- public void testPostOnInvalidUrl() throws Exception {
- //Create upload
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
- servletRequest.setRequestURI(UPLOAD_URL + id.toString());
-
- executeCall(HttpMethod.POST, false);
- }
-
- @Test
- public void testPostWithValidRegexURI() throws Exception {
- reset(uploadStorageService);
- when(uploadStorageService.getUploadURI()).thenReturn("/submission/([a-z0-9]+)/files/upload");
- when(uploadStorageService.create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class))).then(
- new Answer() {
- @Override
- public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
- UploadInfo upload = invocation.getArgument(0);
- upload.setId(id);
-
- when(uploadStorageService.getUploadInfo("/submission/0ae5f8vv4s8c/files/upload/"
- + id.toString(), (String) invocation.getArgument(1))).thenReturn(upload);
- return upload;
- }
- });
-
- //Create upload
- servletRequest.setRequestURI("/submission/0ae5f8vv4s8c/files/upload");
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "submission metadata");
-
- executeCall(HttpMethod.POST, false);
-
- verify(uploadStorageService, times(1)).create(any(UploadInfo.class),
- nullable(String.class));
- assertResponseHeader(HttpHeader.LOCATION, "/submission/0ae5f8vv4s8c/files/upload/" + id.toString());
- assertResponseStatus(HttpServletResponse.SC_CREATED);
-
- //Check data with head request
- servletRequest.setRequestURI("/submission/0ae5f8vv4s8c/files/upload/" + id.toString());
- servletResponse = new MockHttpServletResponse();
- executeCall(HttpMethod.HEAD, false);
-
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is("submission metadata"));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
- }
-
- @Test(expected = PostOnInvalidRequestURIException.class)
- public void testPostWithInvalidRegexURI() throws Exception {
- reset(uploadStorageService);
- when(uploadStorageService.getUploadURI()).thenReturn("/submission/([a-z0-9]+)/files/upload");
- when(uploadStorageService.create(ArgumentMatchers.any(UploadInfo.class), nullable(String.class))).then(
- new Answer() {
- @Override
- public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
- UploadInfo upload = invocation.getArgument(0);
- upload.setId(id);
-
- when(uploadStorageService.getUploadInfo("/submission/0ae5f8vv4s8c/files/upload/"
- + id.toString(), (String) invocation.getArgument(1))).thenReturn(upload);
- return upload;
- }
- });
-
- //Create upload
- servletRequest.setRequestURI("/submission/a+b/files/upload");
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
- servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "submission metadata");
-
- executeCall(HttpMethod.POST, false);
- }
-}
\ No newline at end of file
+ private static final String UPLOAD_URI = "/test/upload";
+
+ // It's important to return relative UPLOAD URLs in the Location header in order to support
+ // HTTPS
+ // proxies
+ // that sit in front of the web app
+ private static final String UPLOAD_URL = UPLOAD_URI + "/";
+
+ private UploadId id;
+
+ @Before
+ public void setUp() throws Exception {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ tusFeature = new CreationExtension();
+ uploadInfo = null;
+
+ id = new UploadId(UUID.randomUUID());
+ servletRequest.setRequestURI(UPLOAD_URI);
+ reset(uploadStorageService);
+ when(uploadStorageService.getUploadURI()).thenReturn(UPLOAD_URI);
+ when(uploadStorageService.create(
+ ArgumentMatchers.any(UploadInfo.class), nullable(String.class)))
+ .then(
+ new Answer() {
+ @Override
+ public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
+ UploadInfo upload = invocation.getArgument(0);
+ upload.setId(id);
+
+ when(uploadStorageService.getUploadInfo(
+ UPLOAD_URL + id.toString(), (String) invocation.getArgument(1)))
+ .thenReturn(upload);
+ return upload;
+ }
+ });
+ }
+
+ @Test
+ public void testOptions() throws Exception {
+ setRequestHeaders();
+
+ executeCall(HttpMethod.OPTIONS, false);
+
+ // If the Server supports this extension, it MUST add creation to the Tus-Extension header.
+ // If the Server supports deferring length, it MUST add creation-defer-length to the
+ // Tus-Extension header.
+ assertResponseHeader(HttpHeader.TUS_EXTENSION, "creation", "creation-defer-length");
+ }
+
+ @Test
+ public void testPostWithLength() throws Exception {
+ // Create upload
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
+
+ executeCall(HttpMethod.POST, false);
+
+ verify(uploadStorageService, times(1)).create(any(UploadInfo.class), nullable(String.class));
+ assertResponseHeader(HttpHeader.LOCATION, UPLOAD_URL + id.toString());
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ // Check data with head request
+ servletRequest.setRequestURI(UPLOAD_URL + id.toString());
+ servletResponse = new MockHttpServletResponse();
+ executeCall(HttpMethod.HEAD, false);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
+
+ // Test Patch request
+ servletRequest = new MockHttpServletRequest();
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
+ servletRequest.setRequestURI(UPLOAD_URL + id.toString());
+ servletResponse = new MockHttpServletResponse();
+ executeCall(HttpMethod.PATCH, false);
+ }
+
+ @Test
+ public void testPostWithDeferredLength() throws Exception {
+ // Create upload
+ servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
+
+ executeCall(HttpMethod.POST, false);
+
+ verify(uploadStorageService, times(1)).create(any(UploadInfo.class), nullable(String.class));
+ assertResponseHeader(HttpHeader.LOCATION, UPLOAD_URL + id.toString());
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ // Check data with head request
+ servletRequest.setRequestURI(UPLOAD_URL + id.toString());
+ servletResponse = new MockHttpServletResponse();
+ executeCall(HttpMethod.HEAD, false);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is("1"));
+
+ // Test Patch request
+ servletRequest = new MockHttpServletRequest();
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
+ servletRequest.setRequestURI(UPLOAD_URL + id.toString());
+ servletResponse = new MockHttpServletResponse();
+ executeCall(HttpMethod.PATCH, false);
+
+ // Re-check head request
+ servletRequest = new MockHttpServletRequest();
+ servletRequest.setRequestURI(UPLOAD_URL + id.toString());
+ servletResponse = new MockHttpServletResponse();
+ executeCall(HttpMethod.HEAD, false);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
+ }
+
+ @Test(expected = InvalidUploadLengthException.class)
+ public void testPostWithoutLength() throws Exception {
+ // Create upload without any length header
+ executeCall(HttpMethod.POST, false);
+ }
+
+ @Test
+ public void testPostWithMetadata() throws Exception {
+ // Create upload
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
+ servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "encoded metadata");
+
+ executeCall(HttpMethod.POST, false);
+
+ verify(uploadStorageService, times(1)).create(any(UploadInfo.class), nullable(String.class));
+ assertResponseHeader(HttpHeader.LOCATION, UPLOAD_URL + id.toString());
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ // Check data with head request
+ servletRequest.setRequestURI(UPLOAD_URL + id.toString());
+ servletResponse = new MockHttpServletResponse();
+ executeCall(HttpMethod.HEAD, false);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is("encoded metadata"));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
+ }
+
+ @Test
+ public void testPostWithAllowedMaxSize() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(100L);
+
+ // Create upload
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 90);
+ executeCall(HttpMethod.POST, false);
+
+ verify(uploadStorageService, times(1)).create(any(UploadInfo.class), nullable(String.class));
+ assertResponseHeader(HttpHeader.LOCATION, UPLOAD_URL + id.toString());
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ // Check data with head request
+ servletRequest.setRequestURI(UPLOAD_URL + id.toString());
+ servletResponse = new MockHttpServletResponse();
+ executeCall(HttpMethod.HEAD, false);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is(nullValue()));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
+ }
+
+ @Test(expected = MaxUploadLengthExceededException.class)
+ public void testPostWithExceededMaxSize() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(100L);
+
+ // Create upload
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 110);
+ executeCall(HttpMethod.POST, false);
+ }
+
+ @Test(expected = PostOnInvalidRequestURIException.class)
+ public void testPostOnInvalidUrl() throws Exception {
+ // Create upload
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
+ servletRequest.setRequestURI(UPLOAD_URL + id.toString());
+
+ executeCall(HttpMethod.POST, false);
+ }
+
+ @Test
+ public void testPostWithValidRegexURI() throws Exception {
+ reset(uploadStorageService);
+ when(uploadStorageService.getUploadURI()).thenReturn("/submission/([a-z0-9]+)/files/upload");
+ when(uploadStorageService.create(
+ ArgumentMatchers.any(UploadInfo.class), nullable(String.class)))
+ .then(
+ new Answer() {
+ @Override
+ public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
+ UploadInfo upload = invocation.getArgument(0);
+ upload.setId(id);
+
+ when(uploadStorageService.getUploadInfo(
+ "/submission/0ae5f8vv4s8c/files/upload/" + id.toString(),
+ (String) invocation.getArgument(1)))
+ .thenReturn(upload);
+ return upload;
+ }
+ });
+
+ // Create upload
+ servletRequest.setRequestURI("/submission/0ae5f8vv4s8c/files/upload");
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
+ servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "submission metadata");
+
+ executeCall(HttpMethod.POST, false);
+
+ verify(uploadStorageService, times(1)).create(any(UploadInfo.class), nullable(String.class));
+ assertResponseHeader(
+ HttpHeader.LOCATION, "/submission/0ae5f8vv4s8c/files/upload/" + id.toString());
+ assertResponseStatus(HttpServletResponse.SC_CREATED);
+
+ // Check data with head request
+ servletRequest.setRequestURI("/submission/0ae5f8vv4s8c/files/upload/" + id.toString());
+ servletResponse = new MockHttpServletResponse();
+ executeCall(HttpMethod.HEAD, false);
+
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA), is("submission metadata"));
+ assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_DEFER_LENGTH), is(nullValue()));
+ }
+
+ @Test(expected = PostOnInvalidRequestURIException.class)
+ public void testPostWithInvalidRegexURI() throws Exception {
+ reset(uploadStorageService);
+ when(uploadStorageService.getUploadURI()).thenReturn("/submission/([a-z0-9]+)/files/upload");
+ when(uploadStorageService.create(
+ ArgumentMatchers.any(UploadInfo.class), nullable(String.class)))
+ .then(
+ new Answer() {
+ @Override
+ public UploadInfo answer(InvocationOnMock invocation) throws Throwable {
+ UploadInfo upload = invocation.getArgument(0);
+ upload.setId(id);
+
+ when(uploadStorageService.getUploadInfo(
+ "/submission/0ae5f8vv4s8c/files/upload/" + id.toString(),
+ (String) invocation.getArgument(1)))
+ .thenReturn(upload);
+ return upload;
+ }
+ });
+
+ // Create upload
+ servletRequest.setRequestURI("/submission/a+b/files/upload");
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 9);
+ servletRequest.addHeader(HttpHeader.UPLOAD_METADATA, "submission metadata");
+
+ executeCall(HttpMethod.POST, false);
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/creation/validation/PostEmptyRequestValidatorTest.java b/src/test/java/me/desair/tus/server/creation/validation/PostEmptyRequestValidatorTest.java
index 0b20c9e..b749559 100644
--- a/src/test/java/me/desair/tus/server/creation/validation/PostEmptyRequestValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/creation/validation/PostEmptyRequestValidatorTest.java
@@ -13,64 +13,64 @@
public class PostEmptyRequestValidatorTest {
- private PostEmptyRequestValidator validator;
-
- private MockHttpServletRequest servletRequest;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new PostEmptyRequestValidator();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(true));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(false));
- assertThat(validator.supports(null), is(false));
+ private PostEmptyRequestValidator validator;
+
+ private MockHttpServletRequest servletRequest;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new PostEmptyRequestValidator();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(true));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(false));
+ assertThat(validator.supports(null), is(false));
+ }
+
+ @Test
+ public void validateMissingContentLength() throws Exception {
+ // We don't set a content length header
+ // servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 3L);
+
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateMissingContentLength() throws Exception {
- //We don't set a content length header
- //servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 3L);
+ // No Exception is thrown
+ }
- //When we validate the request
- try {
- validator.validate(HttpMethod.POST, servletRequest, null, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateContentLengthZero() throws Exception {
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0L);
- //No Exception is thrown
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateContentLengthZero() throws Exception {
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 0L);
+ // No Exception is thrown
+ }
- //When we validate the request
- try {
- validator.validate(HttpMethod.POST, servletRequest, null, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test(expected = InvalidContentLengthException.class)
+ public void validateContentLengthNotZero() throws Exception {
+ servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 10L);
- //No Exception is thrown
- }
-
- @Test(expected = InvalidContentLengthException.class)
- public void validateContentLengthNotZero() throws Exception {
- servletRequest.addHeader(HttpHeader.CONTENT_LENGTH, 10L);
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, null, null);
-
- //Expect a InvalidContentLengthException
- }
-}
\ No newline at end of file
+ // Expect a InvalidContentLengthException
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/creation/validation/PostURIValidatorTest.java b/src/test/java/me/desair/tus/server/creation/validation/PostURIValidatorTest.java
index dce773d..6edb8e8 100644
--- a/src/test/java/me/desair/tus/server/creation/validation/PostURIValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/creation/validation/PostURIValidatorTest.java
@@ -18,86 +18,85 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class PostURIValidatorTest {
- private PostURIValidator validator;
-
- private MockHttpServletRequest servletRequest;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new PostURIValidator();
+ private PostURIValidator validator;
+
+ private MockHttpServletRequest servletRequest;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new PostURIValidator();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(true));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(false));
+ assertThat(validator.supports(null), is(false));
+ }
+
+ @Test
+ public void validateMatchingUrl() throws Exception {
+ servletRequest.setRequestURI("/test/upload");
+ when(uploadStorageService.getUploadURI()).thenReturn("/test/upload");
+
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(true));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(false));
- assertThat(validator.supports(null), is(false));
- }
-
- @Test
- public void validateMatchingUrl() throws Exception {
- servletRequest.setRequestURI("/test/upload");
- when(uploadStorageService.getUploadURI()).thenReturn("/test/upload");
+ // No Exception is thrown
+ }
- try {
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test(expected = PostOnInvalidRequestURIException.class)
+ public void validateInvalidUrl() throws Exception {
+ servletRequest.setRequestURI("/test/upload/12");
+ when(uploadStorageService.getUploadURI()).thenReturn("/test/upload");
- //No Exception is thrown
- }
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- @Test(expected = PostOnInvalidRequestURIException.class)
- public void validateInvalidUrl() throws Exception {
- servletRequest.setRequestURI("/test/upload/12");
- when(uploadStorageService.getUploadURI()).thenReturn("/test/upload");
+ // Expect PostOnInvalidRequestURIException
+ }
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ @Test
+ public void validateMatchingRegexUrl() throws Exception {
+ servletRequest.setRequestURI("/users/1234/files/upload");
+ when(uploadStorageService.getUploadURI()).thenReturn("/users/[0-9]+/files/upload");
- //Expect PostOnInvalidRequestURIException
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateMatchingRegexUrl() throws Exception {
- servletRequest.setRequestURI("/users/1234/files/upload");
- when(uploadStorageService.getUploadURI()).thenReturn("/users/[0-9]+/files/upload");
+ // No Exception is thrown
+ }
- try {
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test(expected = PostOnInvalidRequestURIException.class)
+ public void validateInvalidRegexUrl() throws Exception {
+ servletRequest.setRequestURI("/users/abc123/files/upload");
+ when(uploadStorageService.getUploadURI()).thenReturn("/users/[0-9]+/files/upload");
- //No Exception is thrown
- }
-
- @Test(expected = PostOnInvalidRequestURIException.class)
- public void validateInvalidRegexUrl() throws Exception {
- servletRequest.setRequestURI("/users/abc123/files/upload");
- when(uploadStorageService.getUploadURI()).thenReturn("/users/[0-9]+/files/upload");
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ // Expect PostOnInvalidRequestURIException
+ }
- //Expect PostOnInvalidRequestURIException
- }
+ @Test(expected = PostOnInvalidRequestURIException.class)
+ public void validateInvalidRegexUrlPatchUrl() throws Exception {
+ servletRequest.setRequestURI("/users/1234/files/upload/7669c72a-3f2a-451f-a3b9-9210e7a4c02f");
+ when(uploadStorageService.getUploadURI()).thenReturn("/users/[0-9]+/files/upload");
- @Test(expected = PostOnInvalidRequestURIException.class)
- public void validateInvalidRegexUrlPatchUrl() throws Exception {
- servletRequest.setRequestURI("/users/1234/files/upload/7669c72a-3f2a-451f-a3b9-9210e7a4c02f");
- when(uploadStorageService.getUploadURI()).thenReturn("/users/[0-9]+/files/upload");
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
-
- //Expect PostOnInvalidRequestURIException
- }
-}
\ No newline at end of file
+ // Expect PostOnInvalidRequestURIException
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/creation/validation/UploadDeferLengthValidatorTest.java b/src/test/java/me/desair/tus/server/creation/validation/UploadDeferLengthValidatorTest.java
index aa43a6d..a4dc42b 100644
--- a/src/test/java/me/desair/tus/server/creation/validation/UploadDeferLengthValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/creation/validation/UploadDeferLengthValidatorTest.java
@@ -12,115 +12,114 @@
import org.springframework.mock.web.MockHttpServletRequest;
/**
- * The request MUST include one of the following headers:
- * a) Upload-Length to indicate the size of an entire upload in bytes.
- * b) Upload-Defer-Length: 1 if upload size is not known at the time.
+ * The request MUST include one of the following headers: a) Upload-Length to indicate the size of
+ * an entire upload in bytes. b) Upload-Defer-Length: 1 if upload size is not known at the time.
*/
public class UploadDeferLengthValidatorTest {
- private UploadDeferLengthValidator validator;
-
- private MockHttpServletRequest servletRequest;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new UploadDeferLengthValidator();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(true));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(false));
- assertThat(validator.supports(null), is(false));
+ private UploadDeferLengthValidator validator;
+
+ private MockHttpServletRequest servletRequest;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new UploadDeferLengthValidator();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(true));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(false));
+ assertThat(validator.supports(null), is(false));
+ }
+
+ @Test
+ public void validateUploadLengthPresent() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateUploadLengthPresent() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+ // No Exception is thrown
+ }
- //When we validate the request
- try {
- validator.validate(HttpMethod.POST, servletRequest, null, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateUploadDeferLength1Present() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
- //No Exception is thrown
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateUploadDeferLength1Present() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
+ // No Exception is thrown
+ }
- //When we validate the request
- try {
- validator.validate(HttpMethod.POST, servletRequest, null, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test(expected = InvalidUploadLengthException.class)
+ public void validateUploadLengthAndUploadDeferLength1Present() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
- //No Exception is thrown
- }
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
- @Test(expected = InvalidUploadLengthException.class)
- public void validateUploadLengthAndUploadDeferLength1Present() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 1);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+ // Expect an InvalidUploadLengthException
+ }
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, null, null);
+ @Test(expected = InvalidUploadLengthException.class)
+ public void validateUploadDeferLengthNot1() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 2);
- //Expect an InvalidUploadLengthException
- }
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
- @Test(expected = InvalidUploadLengthException.class)
- public void validateUploadDeferLengthNot1() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_DEFER_LENGTH, 2);
+ // Expect an InvalidUploadLengthException
+ }
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, null, null);
+ @Test(expected = InvalidUploadLengthException.class)
+ public void validateUploadLengthNotPresent() throws Exception {
+ // servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
- //Expect an InvalidUploadLengthException
- }
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
- @Test(expected = InvalidUploadLengthException.class)
- public void validateUploadLengthNotPresent() throws Exception {
- //servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+ // Expect an InvalidUploadLengthException
+ }
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, null, null);
+ @Test
+ public void validateUploadLengthNotPresentOnFinal() throws Exception {
+ // servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+ servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final;1234 5678");
- //Expect an InvalidUploadLengthException
+ // When we validate the request
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateUploadLengthNotPresentOnFinal() throws Exception {
- //servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
- servletRequest.addHeader(HttpHeader.UPLOAD_CONCAT, "final;1234 5678");
-
- //When we validate the request
- try {
- validator.validate(HttpMethod.POST, servletRequest, null, null);
- } catch (Exception ex) {
- fail();
- }
+ // No Exception is thrown
+ }
- //No Exception is thrown
- }
+ @Test(expected = InvalidUploadLengthException.class)
+ public void validateUploadLengthNotNumeric() throws Exception {
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "TEST");
- @Test(expected = InvalidUploadLengthException.class)
- public void validateUploadLengthNotNumeric() throws Exception {
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, "TEST");
+ // When we validate the request
+ validator.validate(HttpMethod.POST, servletRequest, null, null);
- //When we validate the request
- validator.validate(HttpMethod.POST, servletRequest, null, null);
-
- //Expect an InvalidUploadLengthException
- }
-}
\ No newline at end of file
+ // Expect an InvalidUploadLengthException
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/creation/validation/UploadLengthValidatorTest.java b/src/test/java/me/desair/tus/server/creation/validation/UploadLengthValidatorTest.java
index d3f9a54..ace0d25 100644
--- a/src/test/java/me/desair/tus/server/creation/validation/UploadLengthValidatorTest.java
+++ b/src/test/java/me/desair/tus/server/creation/validation/UploadLengthValidatorTest.java
@@ -19,94 +19,93 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class UploadLengthValidatorTest {
- private UploadLengthValidator validator;
-
- private MockHttpServletRequest servletRequest;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- validator = new UploadLengthValidator();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(validator.supports(HttpMethod.GET), is(false));
- assertThat(validator.supports(HttpMethod.POST), is(true));
- assertThat(validator.supports(HttpMethod.PUT), is(false));
- assertThat(validator.supports(HttpMethod.DELETE), is(false));
- assertThat(validator.supports(HttpMethod.HEAD), is(false));
- assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
- assertThat(validator.supports(HttpMethod.PATCH), is(false));
- assertThat(validator.supports(null), is(false));
+ private UploadLengthValidator validator;
+
+ private MockHttpServletRequest servletRequest;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ validator = new UploadLengthValidator();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(validator.supports(HttpMethod.GET), is(false));
+ assertThat(validator.supports(HttpMethod.POST), is(true));
+ assertThat(validator.supports(HttpMethod.PUT), is(false));
+ assertThat(validator.supports(HttpMethod.DELETE), is(false));
+ assertThat(validator.supports(HttpMethod.HEAD), is(false));
+ assertThat(validator.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(validator.supports(HttpMethod.PATCH), is(false));
+ assertThat(validator.supports(null), is(false));
+ }
+
+ @Test
+ public void validateNoMaxUploadLength() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(0L);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateNoMaxUploadLength() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(0L);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+ // No Exception is thrown
+ }
- try {
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateBelowMaxUploadLength() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(400L);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
- //No Exception is thrown
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateBelowMaxUploadLength() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(400L);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+ // No Exception is thrown
+ }
- try {
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateEqualMaxUploadLength() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(300L);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
- //No Exception is thrown
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateEqualMaxUploadLength() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(300L);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+ // No Exception is thrown
+ }
- try {
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test
+ public void validateNoUploadLength() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(300L);
+ // servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
- //No Exception is thrown
+ try {
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
+ } catch (Exception ex) {
+ fail();
}
- @Test
- public void validateNoUploadLength() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(300L);
- //servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+ // No Exception is thrown
+ }
- try {
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- } catch (Exception ex) {
- fail();
- }
+ @Test(expected = MaxUploadLengthExceededException.class)
+ public void validateAboveMaxUploadLength() throws Exception {
+ when(uploadStorageService.getMaxUploadSize()).thenReturn(200L);
+ servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
- //No Exception is thrown
- }
-
- @Test(expected = MaxUploadLengthExceededException.class)
- public void validateAboveMaxUploadLength() throws Exception {
- when(uploadStorageService.getMaxUploadSize()).thenReturn(200L);
- servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 300L);
+ validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
- validator.validate(HttpMethod.POST, servletRequest, uploadStorageService, null);
-
- //Expect a MaxUploadLengthExceededException
- }
-}
\ No newline at end of file
+ // Expect a MaxUploadLengthExceededException
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/download/DownloadGetRequestHandlerTest.java b/src/test/java/me/desair/tus/server/download/DownloadGetRequestHandlerTest.java
index 8750e60..35ff3ea 100644
--- a/src/test/java/me/desair/tus/server/download/DownloadGetRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/download/DownloadGetRequestHandlerTest.java
@@ -9,10 +9,9 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import jakarta.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.UUID;
-import jakarta.servlet.http.HttpServletResponse;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.exception.UploadInProgressException;
@@ -32,112 +31,138 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class DownloadGetRequestHandlerTest {
- private DownloadGetRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new DownloadGetRequestHandler();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(true));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
- @Test
- public void testWithCompletedUploadWithMetadata() throws Exception {
- final UploadId id = new UploadId(UUID.randomUUID());
-
- UploadInfo info = new UploadInfo();
- info.setId(id);
- info.setOffset(10L);
- info.setLength(10L);
- info.setEncodedMetadata("name dGVzdC5qcGc=,type aW1hZ2UvanBlZw==");
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.GET, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, times(1))
- .copyUploadTo(any(UploadInfo.class), any(OutputStream.class));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_OK));
- assertThat(servletResponse.getHeader(HttpHeader.CONTENT_LENGTH), is("10"));
- assertThat(servletResponse.getHeader(HttpHeader.CONTENT_DISPOSITION),
- is("attachment; filename=\"test.jpg\"; filename*=UTF-8''test.jpg"));
- assertThat(servletResponse.getHeader(HttpHeader.CONTENT_TYPE),
- is("image/jpeg"));
- assertThat(servletResponse.getHeader(HttpHeader.UPLOAD_METADATA),
- is("name dGVzdC5qcGc=,type aW1hZ2UvanBlZw=="));
-
- info.setEncodedMetadata("name TmHDr3ZlIGZpbGUudHh0,type dGV4dC9wbGFpbg==");
- handler.process(HttpMethod.GET, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
- assertThat(servletResponse.getHeader(HttpHeader.CONTENT_DISPOSITION),
- is("attachment; filename=\"Naïve file.txt\"; filename*=UTF-8''Na%C3%AFve%20file.txt"));
- }
-
- @Test
- public void testWithCompletedUploadWithoutMetadata() throws Exception {
- final UploadId id = new UploadId(UUID.randomUUID());
-
- UploadInfo info = new UploadInfo();
- info.setId(id);
- info.setOffset(10L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.GET, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, times(1))
- .copyUploadTo(any(UploadInfo.class), any(OutputStream.class));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_OK));
- assertThat(servletResponse.getHeader(HttpHeader.CONTENT_LENGTH), is("10"));
- assertThat(servletResponse.getHeader(HttpHeader.CONTENT_DISPOSITION),
- is("attachment; filename=\"" + id.toString() + "\"; filename*=UTF-8''" + id.toString()));
- assertThat(servletResponse.getHeader(HttpHeader.CONTENT_TYPE), is("application/octet-stream"));
- }
-
- @Test(expected = UploadInProgressException.class)
- public void testWithInProgressUpload() throws Exception {
- final UploadId id = new UploadId(UUID.randomUUID());
-
- UploadInfo info = new UploadInfo();
- info.setId(id);
- info.setOffset(8L);
- info.setLength(10L);
- info.setEncodedMetadata("name dGVzdC5qcGc=,type aW1hZ2UvanBlZw==");
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.GET, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
- }
-
- @Test(expected = UploadInProgressException.class)
- public void testWithUnknownUpload() throws Exception {
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(null);
-
- handler.process(HttpMethod.GET, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, never()).copyUploadTo(any(UploadInfo.class), any(OutputStream.class));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
- }
-
-}
\ No newline at end of file
+ private DownloadGetRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new DownloadGetRequestHandler();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(true));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+
+ @Test
+ public void testWithCompletedUploadWithMetadata() throws Exception {
+ final UploadId id = new UploadId(UUID.randomUUID());
+
+ UploadInfo info = new UploadInfo();
+ info.setId(id);
+ info.setOffset(10L);
+ info.setLength(10L);
+ info.setEncodedMetadata("name dGVzdC5qcGc=,type aW1hZ2UvanBlZw==");
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.GET,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1))
+ .copyUploadTo(any(UploadInfo.class), any(OutputStream.class));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_OK));
+ assertThat(servletResponse.getHeader(HttpHeader.CONTENT_LENGTH), is("10"));
+ assertThat(
+ servletResponse.getHeader(HttpHeader.CONTENT_DISPOSITION),
+ is("attachment; filename=\"test.jpg\"; filename*=UTF-8''test.jpg"));
+ assertThat(servletResponse.getHeader(HttpHeader.CONTENT_TYPE), is("image/jpeg"));
+ assertThat(
+ servletResponse.getHeader(HttpHeader.UPLOAD_METADATA),
+ is("name dGVzdC5qcGc=,type aW1hZ2UvanBlZw=="));
+
+ info.setEncodedMetadata("name TmHDr3ZlIGZpbGUudHh0,type dGV4dC9wbGFpbg==");
+ handler.process(
+ HttpMethod.GET,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+ assertThat(
+ servletResponse.getHeader(HttpHeader.CONTENT_DISPOSITION),
+ is("attachment; filename=\"Naïve file.txt\"; filename*=UTF-8''Na%C3%AFve%20file.txt"));
+ }
+
+ @Test
+ public void testWithCompletedUploadWithoutMetadata() throws Exception {
+ final UploadId id = new UploadId(UUID.randomUUID());
+
+ UploadInfo info = new UploadInfo();
+ info.setId(id);
+ info.setOffset(10L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.GET,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1))
+ .copyUploadTo(any(UploadInfo.class), any(OutputStream.class));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_OK));
+ assertThat(servletResponse.getHeader(HttpHeader.CONTENT_LENGTH), is("10"));
+ assertThat(
+ servletResponse.getHeader(HttpHeader.CONTENT_DISPOSITION),
+ is("attachment; filename=\"" + id.toString() + "\"; filename*=UTF-8''" + id.toString()));
+ assertThat(servletResponse.getHeader(HttpHeader.CONTENT_TYPE), is("application/octet-stream"));
+ }
+
+ @Test(expected = UploadInProgressException.class)
+ public void testWithInProgressUpload() throws Exception {
+ final UploadId id = new UploadId(UUID.randomUUID());
+
+ UploadInfo info = new UploadInfo();
+ info.setId(id);
+ info.setOffset(8L);
+ info.setLength(10L);
+ info.setEncodedMetadata("name dGVzdC5qcGc=,type aW1hZ2UvanBlZw==");
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.GET,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+ }
+
+ @Test(expected = UploadInProgressException.class)
+ public void testWithUnknownUpload() throws Exception {
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(null);
+
+ handler.process(
+ HttpMethod.GET,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never())
+ .copyUploadTo(any(UploadInfo.class), any(OutputStream.class));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/download/DownloadOptionsRequestHandlerTest.java b/src/test/java/me/desair/tus/server/download/DownloadOptionsRequestHandlerTest.java
index 4c6f86a..38c9475 100644
--- a/src/test/java/me/desair/tus/server/download/DownloadOptionsRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/download/DownloadOptionsRequestHandlerTest.java
@@ -5,7 +5,6 @@
import static org.hamcrest.Matchers.containsInAnyOrder;
import java.util.Arrays;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.util.TusServletRequest;
@@ -17,39 +16,43 @@
public class DownloadOptionsRequestHandlerTest {
- private DownloadOptionsRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new DownloadOptionsRequestHandler();
- }
-
- @Test
- public void processListExtensions() throws Exception {
-
- handler.process(HttpMethod.OPTIONS, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), null, null);
-
- assertThat(Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_EXTENSION).split(",")),
- containsInAnyOrder("download"));
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
-}
\ No newline at end of file
+ private DownloadOptionsRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new DownloadOptionsRequestHandler();
+ }
+
+ @Test
+ public void processListExtensions() throws Exception {
+
+ handler.process(
+ HttpMethod.OPTIONS,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ null,
+ null);
+
+ assertThat(
+ Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_EXTENSION).split(",")),
+ containsInAnyOrder("download"));
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/expiration/ExpirationOptionsRequestHandlerTest.java b/src/test/java/me/desair/tus/server/expiration/ExpirationOptionsRequestHandlerTest.java
index adf182c..6a366e7 100644
--- a/src/test/java/me/desair/tus/server/expiration/ExpirationOptionsRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/expiration/ExpirationOptionsRequestHandlerTest.java
@@ -5,7 +5,6 @@
import static org.hamcrest.Matchers.containsInAnyOrder;
import java.util.Arrays;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.util.TusServletRequest;
@@ -15,42 +14,45 @@
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
-
public class ExpirationOptionsRequestHandlerTest {
- private ExpirationOptionsRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new ExpirationOptionsRequestHandler();
- }
-
- @Test
- public void processListExtensions() throws Exception {
-
- handler.process(HttpMethod.OPTIONS, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), null, null);
-
- assertThat(Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_EXTENSION).split(",")),
- containsInAnyOrder("expiration"));
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
-}
\ No newline at end of file
+ private ExpirationOptionsRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new ExpirationOptionsRequestHandler();
+ }
+
+ @Test
+ public void processListExtensions() throws Exception {
+
+ handler.process(
+ HttpMethod.OPTIONS,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ null,
+ null);
+
+ assertThat(
+ Arrays.asList(servletResponse.getHeader(HttpHeader.TUS_EXTENSION).split(",")),
+ containsInAnyOrder("expiration"));
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(true));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/expiration/ExpirationRequestHandlerTest.java b/src/test/java/me/desair/tus/server/expiration/ExpirationRequestHandlerTest.java
index a3a9477..662e05a 100644
--- a/src/test/java/me/desair/tus/server/expiration/ExpirationRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/expiration/ExpirationRequestHandlerTest.java
@@ -13,7 +13,6 @@
import java.text.ParseException;
import java.util.Locale;
import java.util.TimeZone;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.upload.UploadInfo;
@@ -33,157 +32,191 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class ExpirationRequestHandlerTest {
- private static final FastDateFormat DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss",
- TimeZone.getTimeZone(TimeZones.GMT_ID), Locale.US);
-
- private ExpirationRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new ExpirationRequestHandler();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(true));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(false));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(true));
- assertThat(handler.supports(null), is(false));
- }
-
- @Test
- public void testCreatedUpload() throws Exception {
- UploadInfo info = createUploadInfo();
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
- when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(172800000L);
-
- TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
- tusResponse.setHeader(HttpHeader.LOCATION, "/tus/upload/12345");
- handler.process(HttpMethod.POST, new TusServletRequest(servletRequest),
- tusResponse, uploadStorageService, null);
-
- verify(uploadStorageService, times(1)).update(info);
- assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is("1516617791000"));
- }
-
- @Test
- public void testInProgressUpload() throws Exception {
- UploadInfo info = createUploadInfo();
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
- when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(172800000L);
-
- TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- tusResponse, uploadStorageService, null);
-
- verify(uploadStorageService, times(1)).update(info);
- assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is("1516617791000"));
- }
-
- @Test
- public void testNoUpload() throws Exception {
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(null);
- when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(172800000L);
-
- TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- tusResponse, uploadStorageService, null);
-
- verify(uploadStorageService, never()).update(any(UploadInfo.class));
- assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is(nullValue()));
- }
-
- @Test
- public void testFinishedUpload() throws Exception {
- UploadInfo info = createUploadInfo();
- info.setOffset(10L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
- when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(172800000L);
-
- TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- tusResponse, uploadStorageService, null);
-
- //Upload Expires header must always be set
- verify(uploadStorageService, times(1)).update(info);
- assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is("1516617791000"));
- }
-
- @Test
- public void testNullExpiration() throws Exception {
- UploadInfo info = createUploadInfo();
- info.setOffset(8L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
- when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(null);
-
- TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- tusResponse, uploadStorageService, null);
-
- verify(uploadStorageService, never()).update(any(UploadInfo.class));
- assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is(nullValue()));
- }
-
- @Test
- public void testZeroExpiration() throws Exception {
- UploadInfo info = createUploadInfo();
- info.setOffset(8L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
- when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(0L);
-
- TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- tusResponse, uploadStorageService, null);
-
- verify(uploadStorageService, never()).update(any(UploadInfo.class));
- assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is(nullValue()));
- }
-
- @Test
- public void testNegativeExpiration() throws Exception {
- UploadInfo info = createUploadInfo();
- info.setOffset(8L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
- when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(-10L);
-
- TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
- handler.process(HttpMethod.PATCH, new TusServletRequest(servletRequest),
- tusResponse, uploadStorageService, null);
-
- verify(uploadStorageService, never()).update(any(UploadInfo.class));
- assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is(nullValue()));
- }
-
- private UploadInfo createUploadInfo() {
- return new UploadInfo() {
- @Override
- protected long getCurrentTime() {
- try {
- return DATE_FORMAT.parse("2018-01-20 10:43:11").getTime();
- } catch (ParseException e) {
- return 0L;
- }
- }
- };
- }
-
-}
\ No newline at end of file
+ private static final FastDateFormat DATE_FORMAT =
+ FastDateFormat.getInstance(
+ "yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone(TimeZones.GMT_ID), Locale.US);
+
+ private ExpirationRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new ExpirationRequestHandler();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(true));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(false));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(true));
+ assertThat(handler.supports(null), is(false));
+ }
+
+ @Test
+ public void testCreatedUpload() throws Exception {
+ UploadInfo info = createUploadInfo();
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+ when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(172800000L);
+
+ TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
+ tusResponse.setHeader(HttpHeader.LOCATION, "/tus/upload/12345");
+ handler.process(
+ HttpMethod.POST,
+ new TusServletRequest(servletRequest),
+ tusResponse,
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1)).update(info);
+ assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is("1516617791000"));
+ }
+
+ @Test
+ public void testInProgressUpload() throws Exception {
+ UploadInfo info = createUploadInfo();
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+ when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(172800000L);
+
+ TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ tusResponse,
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1)).update(info);
+ assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is("1516617791000"));
+ }
+
+ @Test
+ public void testNoUpload() throws Exception {
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(null);
+ when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(172800000L);
+
+ TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ tusResponse,
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).update(any(UploadInfo.class));
+ assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is(nullValue()));
+ }
+
+ @Test
+ public void testFinishedUpload() throws Exception {
+ UploadInfo info = createUploadInfo();
+ info.setOffset(10L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+ when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(172800000L);
+
+ TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ tusResponse,
+ uploadStorageService,
+ null);
+
+ // Upload Expires header must always be set
+ verify(uploadStorageService, times(1)).update(info);
+ assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is("1516617791000"));
+ }
+
+ @Test
+ public void testNullExpiration() throws Exception {
+ UploadInfo info = createUploadInfo();
+ info.setOffset(8L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+ when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(null);
+
+ TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ tusResponse,
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).update(any(UploadInfo.class));
+ assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is(nullValue()));
+ }
+
+ @Test
+ public void testZeroExpiration() throws Exception {
+ UploadInfo info = createUploadInfo();
+ info.setOffset(8L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+ when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(0L);
+
+ TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ tusResponse,
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).update(any(UploadInfo.class));
+ assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is(nullValue()));
+ }
+
+ @Test
+ public void testNegativeExpiration() throws Exception {
+ UploadInfo info = createUploadInfo();
+ info.setOffset(8L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+ when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(-10L);
+
+ TusServletResponse tusResponse = new TusServletResponse(this.servletResponse);
+ handler.process(
+ HttpMethod.PATCH,
+ new TusServletRequest(servletRequest),
+ tusResponse,
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).update(any(UploadInfo.class));
+ assertThat(tusResponse.getHeader(HttpHeader.UPLOAD_EXPIRES), is(nullValue()));
+ }
+
+ private UploadInfo createUploadInfo() {
+ return new UploadInfo() {
+ @Override
+ protected long getCurrentTime() {
+ try {
+ return DATE_FORMAT.parse("2018-01-20 10:43:11").getTime();
+ } catch (ParseException e) {
+ return 0L;
+ }
+ }
+ };
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/termination/TerminationDeleteRequestHandlerTest.java b/src/test/java/me/desair/tus/server/termination/TerminationDeleteRequestHandlerTest.java
index d52f547..54521e9 100644
--- a/src/test/java/me/desair/tus/server/termination/TerminationDeleteRequestHandlerTest.java
+++ b/src/test/java/me/desair/tus/server/termination/TerminationDeleteRequestHandlerTest.java
@@ -9,9 +9,8 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.util.UUID;
import jakarta.servlet.http.HttpServletResponse;
-
+import java.util.UUID;
import me.desair.tus.server.HttpMethod;
import me.desair.tus.server.upload.UploadId;
import me.desair.tus.server.upload.UploadInfo;
@@ -29,60 +28,68 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class TerminationDeleteRequestHandlerTest {
- private TerminationDeleteRequestHandler handler;
-
- private MockHttpServletRequest servletRequest;
-
- private MockHttpServletResponse servletResponse;
-
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Before
- public void setUp() {
- servletRequest = new MockHttpServletRequest();
- servletResponse = new MockHttpServletResponse();
- handler = new TerminationDeleteRequestHandler();
- }
-
- @Test
- public void supports() throws Exception {
- assertThat(handler.supports(HttpMethod.GET), is(false));
- assertThat(handler.supports(HttpMethod.POST), is(false));
- assertThat(handler.supports(HttpMethod.PUT), is(false));
- assertThat(handler.supports(HttpMethod.DELETE), is(true));
- assertThat(handler.supports(HttpMethod.HEAD), is(false));
- assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
- assertThat(handler.supports(HttpMethod.PATCH), is(false));
- assertThat(handler.supports(null), is(false));
- }
-
- @Test
- public void testWithNotExistingUpload() throws Exception {
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(null);
-
- handler.process(HttpMethod.DELETE, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, never()).terminateUpload(any(UploadInfo.class));
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
- }
-
- @Test
- public void testWithExistingUpload() throws Exception {
- final UploadId id = new UploadId(UUID.randomUUID());
-
- UploadInfo info = new UploadInfo();
- info.setId(id);
- info.setOffset(2L);
- info.setLength(10L);
- when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class))).thenReturn(info);
-
- handler.process(HttpMethod.DELETE, new TusServletRequest(servletRequest),
- new TusServletResponse(servletResponse), uploadStorageService, null);
-
- verify(uploadStorageService, times(1)).terminateUpload(info);
- assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
- }
-
-}
\ No newline at end of file
+ private TerminationDeleteRequestHandler handler;
+
+ private MockHttpServletRequest servletRequest;
+
+ private MockHttpServletResponse servletResponse;
+
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Before
+ public void setUp() {
+ servletRequest = new MockHttpServletRequest();
+ servletResponse = new MockHttpServletResponse();
+ handler = new TerminationDeleteRequestHandler();
+ }
+
+ @Test
+ public void supports() throws Exception {
+ assertThat(handler.supports(HttpMethod.GET), is(false));
+ assertThat(handler.supports(HttpMethod.POST), is(false));
+ assertThat(handler.supports(HttpMethod.PUT), is(false));
+ assertThat(handler.supports(HttpMethod.DELETE), is(true));
+ assertThat(handler.supports(HttpMethod.HEAD), is(false));
+ assertThat(handler.supports(HttpMethod.OPTIONS), is(false));
+ assertThat(handler.supports(HttpMethod.PATCH), is(false));
+ assertThat(handler.supports(null), is(false));
+ }
+
+ @Test
+ public void testWithNotExistingUpload() throws Exception {
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(null);
+
+ handler.process(
+ HttpMethod.DELETE,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, never()).terminateUpload(any(UploadInfo.class));
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
+ }
+
+ @Test
+ public void testWithExistingUpload() throws Exception {
+ final UploadId id = new UploadId(UUID.randomUUID());
+
+ UploadInfo info = new UploadInfo();
+ info.setId(id);
+ info.setOffset(2L);
+ info.setLength(10L);
+ when(uploadStorageService.getUploadInfo(nullable(String.class), nullable(String.class)))
+ .thenReturn(info);
+
+ handler.process(
+ HttpMethod.DELETE,
+ new TusServletRequest(servletRequest),
+ new TusServletResponse(servletResponse),
+ uploadStorageService,
+ null);
+
+ verify(uploadStorageService, times(1)).terminateUpload(info);
+ assertThat(servletResponse.getStatus(), is(HttpServletResponse.SC_NO_CONTENT));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/upload/TimeBasedUploadIdFactoryTest.java b/src/test/java/me/desair/tus/server/upload/TimeBasedUploadIdFactoryTest.java
index 0904455..8d2c6ae 100644
--- a/src/test/java/me/desair/tus/server/upload/TimeBasedUploadIdFactoryTest.java
+++ b/src/test/java/me/desair/tus/server/upload/TimeBasedUploadIdFactoryTest.java
@@ -14,100 +14,100 @@
public class TimeBasedUploadIdFactoryTest {
- private UploadIdFactory idFactory;
-
- @Before
- public void setUp() {
- idFactory = new TimeBasedUploadIdFactory();
- }
-
- @Test(expected = NullPointerException.class)
- public void setUploadURINull() throws Exception {
- idFactory.setUploadURI(null);
- }
-
- @Test
- public void setUploadURINoTrailingSlash() throws Exception {
- idFactory.setUploadURI("/test/upload");
- assertThat(idFactory.getUploadURI(), is("/test/upload"));
- }
-
- @Test
- public void setUploadURIWithTrailingSlash() throws Exception {
- idFactory.setUploadURI("/test/upload/");
- assertThat(idFactory.getUploadURI(), is("/test/upload/"));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void setUploadURIBlank() throws Exception {
- idFactory.setUploadURI(" ");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void setUploadURINoStartingSlash() throws Exception {
- idFactory.setUploadURI("test/upload/");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void setUploadURIEndsWithDollar() throws Exception {
- idFactory.setUploadURI("/test/upload$");
- }
-
- @Test
- public void readUploadId() throws Exception {
- idFactory.setUploadURI("/test/upload");
-
- assertThat(idFactory.readUploadId("/test/upload/1546152320043"),
- hasToString("1546152320043"));
- }
-
- @Test
- public void readUploadIdRegex() throws Exception {
- idFactory.setUploadURI("/users/[0-9]+/files/upload");
-
- assertThat(idFactory.readUploadId("/users/1337/files/upload/1546152320043"),
- hasToString("1546152320043"));
- }
-
- @Test
- public void readUploadIdTrailingSlash() throws Exception {
- idFactory.setUploadURI("/test/upload/");
-
- assertThat(idFactory.readUploadId("/test/upload/1546152320043"),
- hasToString("1546152320043"));
- }
-
- @Test
- public void readUploadIdRegexTrailingSlash() throws Exception {
- idFactory.setUploadURI("/users/[0-9]+/files/upload/");
-
- assertThat(idFactory.readUploadId("/users/123456789/files/upload/1546152320043"),
- hasToString("1546152320043"));
- }
-
- @Test
- public void readUploadIdNoUUID() throws Exception {
- idFactory.setUploadURI("/test/upload");
-
- assertThat(idFactory.readUploadId("/test/upload/not-a-time-value"), is(nullValue()));
- }
-
- @Test
- public void readUploadIdRegexNoMatch() throws Exception {
- idFactory.setUploadURI("/users/[0-9]+/files/upload");
-
- assertThat(idFactory.readUploadId("/users/files/upload/1546152320043"),
- is(nullValue()));
- }
-
- @Test
- public void createId() throws Exception {
- UploadId id = idFactory.createId();
- assertThat(id, not(nullValue()));
- Utils.sleep(10);
- assertThat(Long.parseLong(id.getOriginalObject().toString()),
- greaterThan(System.currentTimeMillis() - 1000L));
- assertThat(Long.parseLong(id.getOriginalObject().toString()),
- lessThan(System.currentTimeMillis()));
- }
-}
\ No newline at end of file
+ private UploadIdFactory idFactory;
+
+ @Before
+ public void setUp() {
+ idFactory = new TimeBasedUploadIdFactory();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void setUploadURINull() throws Exception {
+ idFactory.setUploadURI(null);
+ }
+
+ @Test
+ public void setUploadURINoTrailingSlash() throws Exception {
+ idFactory.setUploadURI("/test/upload");
+ assertThat(idFactory.getUploadURI(), is("/test/upload"));
+ }
+
+ @Test
+ public void setUploadURIWithTrailingSlash() throws Exception {
+ idFactory.setUploadURI("/test/upload/");
+ assertThat(idFactory.getUploadURI(), is("/test/upload/"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void setUploadURIBlank() throws Exception {
+ idFactory.setUploadURI(" ");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void setUploadURINoStartingSlash() throws Exception {
+ idFactory.setUploadURI("test/upload/");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void setUploadURIEndsWithDollar() throws Exception {
+ idFactory.setUploadURI("/test/upload$");
+ }
+
+ @Test
+ public void readUploadId() throws Exception {
+ idFactory.setUploadURI("/test/upload");
+
+ assertThat(idFactory.readUploadId("/test/upload/1546152320043"), hasToString("1546152320043"));
+ }
+
+ @Test
+ public void readUploadIdRegex() throws Exception {
+ idFactory.setUploadURI("/users/[0-9]+/files/upload");
+
+ assertThat(
+ idFactory.readUploadId("/users/1337/files/upload/1546152320043"),
+ hasToString("1546152320043"));
+ }
+
+ @Test
+ public void readUploadIdTrailingSlash() throws Exception {
+ idFactory.setUploadURI("/test/upload/");
+
+ assertThat(idFactory.readUploadId("/test/upload/1546152320043"), hasToString("1546152320043"));
+ }
+
+ @Test
+ public void readUploadIdRegexTrailingSlash() throws Exception {
+ idFactory.setUploadURI("/users/[0-9]+/files/upload/");
+
+ assertThat(
+ idFactory.readUploadId("/users/123456789/files/upload/1546152320043"),
+ hasToString("1546152320043"));
+ }
+
+ @Test
+ public void readUploadIdNoUUID() throws Exception {
+ idFactory.setUploadURI("/test/upload");
+
+ assertThat(idFactory.readUploadId("/test/upload/not-a-time-value"), is(nullValue()));
+ }
+
+ @Test
+ public void readUploadIdRegexNoMatch() throws Exception {
+ idFactory.setUploadURI("/users/[0-9]+/files/upload");
+
+ assertThat(idFactory.readUploadId("/users/files/upload/1546152320043"), is(nullValue()));
+ }
+
+ @Test
+ public void createId() throws Exception {
+ UploadId id = idFactory.createId();
+ assertThat(id, not(nullValue()));
+ Utils.sleep(10);
+ assertThat(
+ Long.parseLong(id.getOriginalObject().toString()),
+ greaterThan(System.currentTimeMillis() - 1000L));
+ assertThat(
+ Long.parseLong(id.getOriginalObject().toString()), lessThan(System.currentTimeMillis()));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/upload/UUIDUploadIdFactoryTest.java b/src/test/java/me/desair/tus/server/upload/UUIDUploadIdFactoryTest.java
index e7dd0a5..6f00470 100644
--- a/src/test/java/me/desair/tus/server/upload/UUIDUploadIdFactoryTest.java
+++ b/src/test/java/me/desair/tus/server/upload/UUIDUploadIdFactoryTest.java
@@ -11,95 +11,100 @@
public class UUIDUploadIdFactoryTest {
- private UploadIdFactory idFactory;
-
- @Before
- public void setUp() {
- idFactory = new UUIDUploadIdFactory();
- }
-
- @Test(expected = NullPointerException.class)
- public void setUploadURINull() throws Exception {
- idFactory.setUploadURI(null);
- }
-
- @Test
- public void setUploadURINoTrailingSlash() throws Exception {
- idFactory.setUploadURI("/test/upload");
- assertThat(idFactory.getUploadURI(), is("/test/upload"));
- }
-
- @Test
- public void setUploadURIWithTrailingSlash() throws Exception {
- idFactory.setUploadURI("/test/upload/");
- assertThat(idFactory.getUploadURI(), is("/test/upload/"));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void setUploadURIBlank() throws Exception {
- idFactory.setUploadURI(" ");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void setUploadURINoStartingSlash() throws Exception {
- idFactory.setUploadURI("test/upload/");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void setUploadURIEndsWithDollar() throws Exception {
- idFactory.setUploadURI("/test/upload$");
- }
-
- @Test
- public void readUploadId() throws Exception {
- idFactory.setUploadURI("/test/upload");
-
- assertThat(idFactory.readUploadId("/test/upload/1911e8a4-6939-490c-b58b-a5d70f8d91fb"),
- hasToString("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
- }
-
- @Test
- public void readUploadIdRegex() throws Exception {
- idFactory.setUploadURI("/users/[0-9]+/files/upload");
-
- assertThat(idFactory.readUploadId("/users/1337/files/upload/1911e8a4-6939-490c-b58b-a5d70f8d91fb"),
- hasToString("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
- }
-
- @Test
- public void readUploadIdTrailingSlash() throws Exception {
- idFactory.setUploadURI("/test/upload/");
-
- assertThat(idFactory.readUploadId("/test/upload/1911e8a4-6939-490c-b58b-a5d70f8d91fb"),
- hasToString("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
- }
-
- @Test
- public void readUploadIdRegexTrailingSlash() throws Exception {
- idFactory.setUploadURI("/users/[0-9]+/files/upload/");
-
- assertThat(idFactory.readUploadId("/users/123456789/files/upload/1911e8a4-6939-490c-b58b-a5d70f8d91fb"),
- hasToString("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
- }
-
- @Test
- public void readUploadIdNoUUID() throws Exception {
- idFactory.setUploadURI("/test/upload");
-
- assertThat(idFactory.readUploadId("/test/upload/not-a-uuid-value"), is(nullValue()));
- }
-
- @Test
- public void readUploadIdRegexNoMatch() throws Exception {
- idFactory.setUploadURI("/users/[0-9]+/files/upload");
-
- assertThat(idFactory.readUploadId("/users/files/upload/1911e8a4-6939-490c-b58b-a5d70f8d91fb"),
- is(nullValue()));
- }
-
- @Test
- public void createId() throws Exception {
- assertThat(idFactory.createId(), not(nullValue()));
- }
-
-}
\ No newline at end of file
+ private UploadIdFactory idFactory;
+
+ @Before
+ public void setUp() {
+ idFactory = new UUIDUploadIdFactory();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void setUploadURINull() throws Exception {
+ idFactory.setUploadURI(null);
+ }
+
+ @Test
+ public void setUploadURINoTrailingSlash() throws Exception {
+ idFactory.setUploadURI("/test/upload");
+ assertThat(idFactory.getUploadURI(), is("/test/upload"));
+ }
+
+ @Test
+ public void setUploadURIWithTrailingSlash() throws Exception {
+ idFactory.setUploadURI("/test/upload/");
+ assertThat(idFactory.getUploadURI(), is("/test/upload/"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void setUploadURIBlank() throws Exception {
+ idFactory.setUploadURI(" ");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void setUploadURINoStartingSlash() throws Exception {
+ idFactory.setUploadURI("test/upload/");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void setUploadURIEndsWithDollar() throws Exception {
+ idFactory.setUploadURI("/test/upload$");
+ }
+
+ @Test
+ public void readUploadId() throws Exception {
+ idFactory.setUploadURI("/test/upload");
+
+ assertThat(
+ idFactory.readUploadId("/test/upload/1911e8a4-6939-490c-b58b-a5d70f8d91fb"),
+ hasToString("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+ }
+
+ @Test
+ public void readUploadIdRegex() throws Exception {
+ idFactory.setUploadURI("/users/[0-9]+/files/upload");
+
+ assertThat(
+ idFactory.readUploadId("/users/1337/files/upload/1911e8a4-6939-490c-b58b-a5d70f8d91fb"),
+ hasToString("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+ }
+
+ @Test
+ public void readUploadIdTrailingSlash() throws Exception {
+ idFactory.setUploadURI("/test/upload/");
+
+ assertThat(
+ idFactory.readUploadId("/test/upload/1911e8a4-6939-490c-b58b-a5d70f8d91fb"),
+ hasToString("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+ }
+
+ @Test
+ public void readUploadIdRegexTrailingSlash() throws Exception {
+ idFactory.setUploadURI("/users/[0-9]+/files/upload/");
+
+ assertThat(
+ idFactory.readUploadId(
+ "/users/123456789/files/upload/1911e8a4-6939-490c-b58b-a5d70f8d91fb"),
+ hasToString("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+ }
+
+ @Test
+ public void readUploadIdNoUUID() throws Exception {
+ idFactory.setUploadURI("/test/upload");
+
+ assertThat(idFactory.readUploadId("/test/upload/not-a-uuid-value"), is(nullValue()));
+ }
+
+ @Test
+ public void readUploadIdRegexNoMatch() throws Exception {
+ idFactory.setUploadURI("/users/[0-9]+/files/upload");
+
+ assertThat(
+ idFactory.readUploadId("/users/files/upload/1911e8a4-6939-490c-b58b-a5d70f8d91fb"),
+ is(nullValue()));
+ }
+
+ @Test
+ public void createId() throws Exception {
+ assertThat(idFactory.createId(), not(nullValue()));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/upload/UploadIdTest.java b/src/test/java/me/desair/tus/server/upload/UploadIdTest.java
index 6253cd9..00458c6 100644
--- a/src/test/java/me/desair/tus/server/upload/UploadIdTest.java
+++ b/src/test/java/me/desair/tus/server/upload/UploadIdTest.java
@@ -5,81 +5,80 @@
import static org.junit.Assert.assertNotEquals;
import java.util.UUID;
-
import org.junit.Test;
public class UploadIdTest {
- @Test
- public void getOriginalObjectUUID() {
- UUID id = UUID.randomUUID();
- UploadId uploadId = new UploadId(id);
- assertEquals(id.toString(), uploadId.toString());
- assertEquals(id, uploadId.getOriginalObject());
- }
-
- @Test
- public void getOriginalObjectLong() {
- UploadId uploadId = new UploadId(1337L);
- assertEquals("1337", uploadId.toString());
- assertEquals(1337L, uploadId.getOriginalObject());
- }
-
- @Test(expected = NullPointerException.class)
- public void testNullConstructor() {
- new UploadId(null);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testBlankConstructor() {
- new UploadId(" \t");
- }
-
- @Test
- public void toStringNotYetUrlSafe() {
- UploadId uploadId = new UploadId("my test id/1");
- assertEquals("my+test+id%2F1", uploadId.toString());
- }
-
- @Test
- public void toStringNotYetUrlSafe2() {
- UploadId uploadId = new UploadId("id+%2F1+/+1");
- assertEquals("id+%2F1+/+1", uploadId.toString());
- }
-
- @Test
- public void toStringAlreadyUrlSafe() {
- UploadId uploadId = new UploadId("my+test+id%2F1");
- assertEquals("my+test+id%2F1", uploadId.toString());
- }
-
- @Test
- public void toStringWithInternalDecoderException() {
- String test = "Invalid % value";
- UploadId id = new UploadId(test);
- assertEquals("Invalid % value", id.toString());
- }
-
- @Test
- public void equalsSameUrlSafeValue() {
- UploadId id1 = new UploadId("id%2F1");
- UploadId id2 = new UploadId("id/1");
- UploadId id3 = new UploadId("id/1");
-
- assertEquals(id1, id2);
- assertEquals(id2, id3);
- assertEquals(id1, id1);
- assertNotEquals(id1, null);
- assertFalse(id1.equals(UUID.randomUUID()));
- }
-
- @Test
- public void hashCodeSameUrlSafeValue() {
- UploadId id1 = new UploadId("id%2F1");
- UploadId id2 = new UploadId("id/1");
- UploadId id3 = new UploadId("id/1");
-
- assertEquals(id1.hashCode(), id2.hashCode());
- assertEquals(id2.hashCode(), id3.hashCode());
- }
-}
\ No newline at end of file
+ @Test
+ public void getOriginalObjectUUID() {
+ UUID id = UUID.randomUUID();
+ UploadId uploadId = new UploadId(id);
+ assertEquals(id.toString(), uploadId.toString());
+ assertEquals(id, uploadId.getOriginalObject());
+ }
+
+ @Test
+ public void getOriginalObjectLong() {
+ UploadId uploadId = new UploadId(1337L);
+ assertEquals("1337", uploadId.toString());
+ assertEquals(1337L, uploadId.getOriginalObject());
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullConstructor() {
+ new UploadId(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testBlankConstructor() {
+ new UploadId(" \t");
+ }
+
+ @Test
+ public void toStringNotYetUrlSafe() {
+ UploadId uploadId = new UploadId("my test id/1");
+ assertEquals("my+test+id%2F1", uploadId.toString());
+ }
+
+ @Test
+ public void toStringNotYetUrlSafe2() {
+ UploadId uploadId = new UploadId("id+%2F1+/+1");
+ assertEquals("id+%2F1+/+1", uploadId.toString());
+ }
+
+ @Test
+ public void toStringAlreadyUrlSafe() {
+ UploadId uploadId = new UploadId("my+test+id%2F1");
+ assertEquals("my+test+id%2F1", uploadId.toString());
+ }
+
+ @Test
+ public void toStringWithInternalDecoderException() {
+ String test = "Invalid % value";
+ UploadId id = new UploadId(test);
+ assertEquals("Invalid % value", id.toString());
+ }
+
+ @Test
+ public void equalsSameUrlSafeValue() {
+ UploadId id1 = new UploadId("id%2F1");
+ UploadId id2 = new UploadId("id/1");
+ UploadId id3 = new UploadId("id/1");
+
+ assertEquals(id1, id2);
+ assertEquals(id2, id3);
+ assertEquals(id1, id1);
+ assertNotEquals(id1, null);
+ assertFalse(id1.equals(UUID.randomUUID()));
+ }
+
+ @Test
+ public void hashCodeSameUrlSafeValue() {
+ UploadId id1 = new UploadId("id%2F1");
+ UploadId id2 = new UploadId("id/1");
+ UploadId id3 = new UploadId("id/1");
+
+ assertEquals(id1.hashCode(), id2.hashCode());
+ assertEquals(id2.hashCode(), id3.hashCode());
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/upload/UploadInfoTest.java b/src/test/java/me/desair/tus/server/upload/UploadInfoTest.java
index ca695e4..8c36548 100644
--- a/src/test/java/me/desair/tus/server/upload/UploadInfoTest.java
+++ b/src/test/java/me/desair/tus/server/upload/UploadInfoTest.java
@@ -14,7 +14,6 @@
import java.text.ParseException;
import java.util.Stack;
import java.util.UUID;
-
import me.desair.tus.server.HttpHeader;
import me.desair.tus.server.util.Utils;
import org.apache.commons.lang3.time.DateFormatUtils;
@@ -23,253 +22,261 @@
public class UploadInfoTest {
- @Test
- public void hasMetadata() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setEncodedMetadata("Encoded Metadata");
- assertTrue(info.hasMetadata());
- }
-
- @Test
- public void hasMetadataFalse() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setEncodedMetadata(null);
- assertFalse(info.hasMetadata());
- }
-
- @Test
- public void testGetMetadataMultipleValues() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setEncodedMetadata(
- "filename d29ybGRfZG9taW5hdGlvbiBwbGFuLnBkZg==," +
- "filesize MTEya2I=, " +
- "mimetype \tYXBwbGljYXRpb24vcGRm , " +
- "scanned , ,, " +
- "user\t546L5LqU \t ");
-
- assertThat(info.getMetadata(), allOf(hasSize(5),
- hasEntry("filename", "world_domination plan.pdf"),
- hasEntry("filesize", "112kb"),
- hasEntry("mimetype", "application/pdf"),
- hasEntry("scanned", null),
- hasEntry("user", "王五"))
- );
- }
-
- @Test
- public void testGetMetadataSingleValues() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setEncodedMetadata("filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
-
- assertThat(info.getMetadata(), allOf(hasSize(1),
- hasEntry("filename", "world_domination_plan.pdf"))
- );
- }
-
- @Test
- public void testGetMetadataNull() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setEncodedMetadata(null);
- assertTrue(info.getMetadata().isEmpty());
- }
-
- @Test
- public void hasLength() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setLength(10L);
- assertTrue(info.hasLength());
- }
-
- @Test
- public void hasLengthFalse() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setLength(null);
- assertFalse(info.hasLength());
- }
-
- @Test
- public void isUploadInProgressNoLengthNoOffset() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setLength(null);
- info.setOffset(null);
- assertTrue(info.isUploadInProgress());
- }
-
- @Test
- public void isUploadInProgressNoLengthWithOffset() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setLength(null);
- info.setOffset(10L);
- assertTrue(info.isUploadInProgress());
- }
-
- @Test
- public void isUploadInProgressOffsetDoesNotMatchLength() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setLength(10L);
- info.setOffset(8L);
- assertTrue(info.isUploadInProgress());
- }
-
- @Test
- public void isUploadInProgressOffsetMatchesLength() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setLength(10L);
- info.setOffset(10L);
- assertFalse(info.isUploadInProgress());
- }
-
- @Test
- public void testEquals() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setLength(10L);
- info1.setOffset(5L);
- info1.setEncodedMetadata("Encoded-Metadata");
- info1.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
-
- UploadInfo info2 = new UploadInfo();
- info2.setLength(10L);
- info2.setOffset(5L);
- info2.setEncodedMetadata("Encoded-Metadata");
- info2.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
-
- UploadInfo info3 = new UploadInfo();
- info3.setLength(9L);
- info3.setOffset(5L);
- info3.setEncodedMetadata("Encoded-Metadata");
- info3.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
-
- UploadInfo info4 = new UploadInfo();
- info4.setLength(10L);
- info4.setOffset(6L);
- info4.setEncodedMetadata("Encoded-Metadata");
- info4.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
-
- UploadInfo info5 = new UploadInfo();
- info5.setLength(10L);
- info5.setOffset(5L);
- info5.setEncodedMetadata("Encoded-Metadatas");
- info5.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
-
- UploadInfo info6 = new UploadInfo();
- info6.setLength(10L);
- info6.setOffset(5L);
- info6.setEncodedMetadata("Encoded-Metadata");
- info6.setId(new UploadId("1911e8a4-6939-490c-c58b-a5d70f8d91fb"));
-
- assertTrue(info1.equals(info1));
- assertTrue(info1.equals(info2));
- assertFalse(info1.equals(null));
- assertFalse(info1.equals(new Object()));
- assertFalse(info1.equals(info3));
- assertFalse(info1.equals(info4));
- assertFalse(info1.equals(info5));
- assertFalse(info1.equals(info6));
- }
-
- @Test
- public void testHashCode() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setLength(10L);
- info1.setOffset(5L);
- info1.setEncodedMetadata("Encoded-Metadata");
- info1.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
-
- UploadInfo info2 = new UploadInfo();
- info2.setLength(10L);
- info2.setOffset(5L);
- info2.setEncodedMetadata("Encoded-Metadata");
- info2.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
-
- assertTrue(info1.hashCode() == info2.hashCode());
- }
-
- @Test
- public void testGetNameAndTypeWithMetadata() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setEncodedMetadata("name dGVzdC5qcGc=,type aW1hZ2UvanBlZw==");
-
- assertThat(info.getFileName(), is("test.jpg"));
- assertThat(info.getFileMimeType(), is("image/jpeg"));
- }
-
- @Test
- public void testGetNameAndTypeWithoutMetadata() throws Exception {
- UploadInfo info = new UploadInfo();
- final UploadId id = new UploadId(UUID.randomUUID());
- info.setId(id);
-
- assertThat(info.getFileName(), is(id.toString()));
- assertThat(info.getFileMimeType(), is("application/octet-stream"));
- }
-
- @Test
- public void testExpiration() throws Exception {
- UploadInfo info1 = new UploadInfo();
- assertFalse(info1.isExpired());
-
- UploadInfo info2 = new UploadInfo() {
- @Override
- protected long getCurrentTime() {
- try {
- return DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse("2018-01-20T10:43:11").getTime();
- } catch (ParseException e) {
- return 0L;
- }
+ @Test
+ public void hasMetadata() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setEncodedMetadata("Encoded Metadata");
+ assertTrue(info.hasMetadata());
+ }
+
+ @Test
+ public void hasMetadataFalse() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setEncodedMetadata(null);
+ assertFalse(info.hasMetadata());
+ }
+
+ @Test
+ public void testGetMetadataMultipleValues() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setEncodedMetadata(
+ "filename d29ybGRfZG9taW5hdGlvbiBwbGFuLnBkZg==,"
+ + "filesize MTEya2I=, "
+ + "mimetype \tYXBwbGljYXRpb24vcGRm , "
+ + "scanned , ,, "
+ + "user\t546L5LqU \t ");
+
+ assertThat(
+ info.getMetadata(),
+ allOf(
+ hasSize(5),
+ hasEntry("filename", "world_domination plan.pdf"),
+ hasEntry("filesize", "112kb"),
+ hasEntry("mimetype", "application/pdf"),
+ hasEntry("scanned", null),
+ hasEntry("user", "王五")));
+ }
+
+ @Test
+ public void testGetMetadataSingleValues() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setEncodedMetadata("filename d29ybGRfZG9taW5hdGlvbl9wbGFuLnBkZg==");
+
+ assertThat(
+ info.getMetadata(), allOf(hasSize(1), hasEntry("filename", "world_domination_plan.pdf")));
+ }
+
+ @Test
+ public void testGetMetadataNull() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setEncodedMetadata(null);
+ assertTrue(info.getMetadata().isEmpty());
+ }
+
+ @Test
+ public void hasLength() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setLength(10L);
+ assertTrue(info.hasLength());
+ }
+
+ @Test
+ public void hasLengthFalse() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setLength(null);
+ assertFalse(info.hasLength());
+ }
+
+ @Test
+ public void isUploadInProgressNoLengthNoOffset() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setLength(null);
+ info.setOffset(null);
+ assertTrue(info.isUploadInProgress());
+ }
+
+ @Test
+ public void isUploadInProgressNoLengthWithOffset() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setLength(null);
+ info.setOffset(10L);
+ assertTrue(info.isUploadInProgress());
+ }
+
+ @Test
+ public void isUploadInProgressOffsetDoesNotMatchLength() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setLength(10L);
+ info.setOffset(8L);
+ assertTrue(info.isUploadInProgress());
+ }
+
+ @Test
+ public void isUploadInProgressOffsetMatchesLength() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setLength(10L);
+ info.setOffset(10L);
+ assertFalse(info.isUploadInProgress());
+ }
+
+ @Test
+ public void testEquals() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setLength(10L);
+ info1.setOffset(5L);
+ info1.setEncodedMetadata("Encoded-Metadata");
+ info1.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+
+ UploadInfo info2 = new UploadInfo();
+ info2.setLength(10L);
+ info2.setOffset(5L);
+ info2.setEncodedMetadata("Encoded-Metadata");
+ info2.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+
+ UploadInfo info3 = new UploadInfo();
+ info3.setLength(9L);
+ info3.setOffset(5L);
+ info3.setEncodedMetadata("Encoded-Metadata");
+ info3.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+
+ UploadInfo info4 = new UploadInfo();
+ info4.setLength(10L);
+ info4.setOffset(6L);
+ info4.setEncodedMetadata("Encoded-Metadata");
+ info4.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+
+ UploadInfo info5 = new UploadInfo();
+ info5.setLength(10L);
+ info5.setOffset(5L);
+ info5.setEncodedMetadata("Encoded-Metadatas");
+ info5.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+
+ UploadInfo info6 = new UploadInfo();
+ info6.setLength(10L);
+ info6.setOffset(5L);
+ info6.setEncodedMetadata("Encoded-Metadata");
+ info6.setId(new UploadId("1911e8a4-6939-490c-c58b-a5d70f8d91fb"));
+
+ assertTrue(info1.equals(info1));
+ assertTrue(info1.equals(info2));
+ assertFalse(info1.equals(null));
+ assertFalse(info1.equals(new Object()));
+ assertFalse(info1.equals(info3));
+ assertFalse(info1.equals(info4));
+ assertFalse(info1.equals(info5));
+ assertFalse(info1.equals(info6));
+ }
+
+ @Test
+ public void testHashCode() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setLength(10L);
+ info1.setOffset(5L);
+ info1.setEncodedMetadata("Encoded-Metadata");
+ info1.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+
+ UploadInfo info2 = new UploadInfo();
+ info2.setLength(10L);
+ info2.setOffset(5L);
+ info2.setEncodedMetadata("Encoded-Metadata");
+ info2.setId(new UploadId("1911e8a4-6939-490c-b58b-a5d70f8d91fb"));
+
+ assertTrue(info1.hashCode() == info2.hashCode());
+ }
+
+ @Test
+ public void testGetNameAndTypeWithMetadata() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setEncodedMetadata("name dGVzdC5qcGc=,type aW1hZ2UvanBlZw==");
+
+ assertThat(info.getFileName(), is("test.jpg"));
+ assertThat(info.getFileMimeType(), is("image/jpeg"));
+ }
+
+ @Test
+ public void testGetNameAndTypeWithoutMetadata() throws Exception {
+ UploadInfo info = new UploadInfo();
+ final UploadId id = new UploadId(UUID.randomUUID());
+ info.setId(id);
+
+ assertThat(info.getFileName(), is(id.toString()));
+ assertThat(info.getFileMimeType(), is("application/octet-stream"));
+ }
+
+ @Test
+ public void testExpiration() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ assertFalse(info1.isExpired());
+
+ UploadInfo info2 =
+ new UploadInfo() {
+ @Override
+ protected long getCurrentTime() {
+ try {
+ return DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT
+ .parse("2018-01-20T10:43:11")
+ .getTime();
+ } catch (ParseException e) {
+ return 0L;
}
+ }
};
- info2.updateExpiration(172800000L);
- assertFalse(info2.isExpired());
-
- final Stack dateStack = new Stack<>();
- //Current time stamp to check expiration
- dateStack.push(DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse("2018-01-23T10:43:11").getTime());
- //Current time stamp to calculate expiration
- dateStack.push(DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse("2018-01-20T10:43:11").getTime());
- //Creation time stamp
- dateStack.push(DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse("2018-01-20T10:40:39").getTime());
-
- UploadInfo info3 = new UploadInfo() {
- @Override
- protected long getCurrentTime() {
- return dateStack.pop();
- }
+ info2.updateExpiration(172800000L);
+ assertFalse(info2.isExpired());
+
+ final Stack dateStack = new Stack<>();
+ // Current time stamp to check expiration
+ dateStack.push(
+ DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse("2018-01-23T10:43:11").getTime());
+ // Current time stamp to calculate expiration
+ dateStack.push(
+ DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse("2018-01-20T10:43:11").getTime());
+ // Creation time stamp
+ dateStack.push(
+ DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse("2018-01-20T10:40:39").getTime());
+
+ UploadInfo info3 =
+ new UploadInfo() {
+ @Override
+ protected long getCurrentTime() {
+ return dateStack.pop();
+ }
};
- info3.updateExpiration(172800000L);
- assertTrue(info3.isExpired());
- }
-
- @Test
- public void testGetCreationTimestamp() throws Exception {
- UploadInfo info = new UploadInfo();
- Utils.sleep(10);
-
- assertThat(info.getCreationTimestamp(), greaterThan(System.currentTimeMillis() - 500L));
- assertThat(info.getCreationTimestamp(), lessThan(System.currentTimeMillis()));
- }
-
- @Test
- public void testGetCreatorIpAddressesNull() throws Exception {
- UploadInfo info = new UploadInfo();
- assertThat(info.getCreatorIpAddresses(), nullValue());
- }
-
- @Test
- public void testGetCreatorIpAddressesWithoutXForwardedFor() throws Exception {
- MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- servletRequest.setRemoteAddr("10.11.12.13");
-
- UploadInfo info = new UploadInfo(servletRequest);
- assertThat(info.getCreatorIpAddresses(), is("10.11.12.13"));
- }
-
- @Test
- public void testGetCreatorIpAddressesWithXForwardedFor() throws Exception {
- MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- servletRequest.setRemoteAddr("10.11.12.13");
- servletRequest.addHeader(HttpHeader.X_FORWARDED_FOR, "24.23.22.21, 192.168.1.1");
-
- UploadInfo info = new UploadInfo(servletRequest);
- assertThat(info.getCreatorIpAddresses(), is("24.23.22.21, 192.168.1.1, 10.11.12.13"));
- }
-}
\ No newline at end of file
+ info3.updateExpiration(172800000L);
+ assertTrue(info3.isExpired());
+ }
+
+ @Test
+ public void testGetCreationTimestamp() throws Exception {
+ UploadInfo info = new UploadInfo();
+ Utils.sleep(10);
+
+ assertThat(info.getCreationTimestamp(), greaterThan(System.currentTimeMillis() - 500L));
+ assertThat(info.getCreationTimestamp(), lessThan(System.currentTimeMillis()));
+ }
+
+ @Test
+ public void testGetCreatorIpAddressesNull() throws Exception {
+ UploadInfo info = new UploadInfo();
+ assertThat(info.getCreatorIpAddresses(), nullValue());
+ }
+
+ @Test
+ public void testGetCreatorIpAddressesWithoutXForwardedFor() throws Exception {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.setRemoteAddr("10.11.12.13");
+
+ UploadInfo info = new UploadInfo(servletRequest);
+ assertThat(info.getCreatorIpAddresses(), is("10.11.12.13"));
+ }
+
+ @Test
+ public void testGetCreatorIpAddressesWithXForwardedFor() throws Exception {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.setRemoteAddr("10.11.12.13");
+ servletRequest.addHeader(HttpHeader.X_FORWARDED_FOR, "24.23.22.21, 192.168.1.1");
+
+ UploadInfo info = new UploadInfo(servletRequest);
+ assertThat(info.getCreatorIpAddresses(), is("24.23.22.21, 192.168.1.1, 10.11.12.13"));
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/upload/concatenation/UploadInputStreamEnumerationTest.java b/src/test/java/me/desair/tus/server/upload/concatenation/UploadInputStreamEnumerationTest.java
index 0fee31a..abec39f 100644
--- a/src/test/java/me/desair/tus/server/upload/concatenation/UploadInputStreamEnumerationTest.java
+++ b/src/test/java/me/desair/tus/server/upload/concatenation/UploadInputStreamEnumerationTest.java
@@ -10,7 +10,6 @@
import java.util.Arrays;
import java.util.LinkedList;
import java.util.UUID;
-
import me.desair.tus.server.upload.UploadId;
import me.desair.tus.server.upload.UploadInfo;
import me.desair.tus.server.upload.UploadStorageService;
@@ -23,125 +22,134 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class UploadInputStreamEnumerationTest {
- @Mock
- private UploadStorageService uploadStorageService;
-
- @Test
- public void hasMoreElements() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
-
- UploadInfo info2 = new UploadInfo();
- info2.setId(new UploadId(UUID.randomUUID()));
-
- UploadInfo info3 = new UploadInfo();
- info3.setId(new UploadId(UUID.randomUUID()));
-
- when(uploadStorageService.getUploadedBytes(info1.getId()))
- .thenReturn(IOUtils.toInputStream("Upload 1", StandardCharsets.UTF_8));
- when(uploadStorageService.getUploadedBytes(info2.getId()))
- .thenReturn(IOUtils.toInputStream("Upload 2", StandardCharsets.UTF_8));
- when(uploadStorageService.getUploadedBytes(info3.getId()))
- .thenReturn(IOUtils.toInputStream("Upload 3", StandardCharsets.UTF_8));
-
- UploadInputStreamEnumeration uploadInputStreamEnumeration
- = new UploadInputStreamEnumeration(Arrays.asList(info1, info2, info3), uploadStorageService);
-
- assertTrue(uploadInputStreamEnumeration.hasMoreElements());
- assertEquals("Upload 1", IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
- assertTrue(uploadInputStreamEnumeration.hasMoreElements());
- assertEquals("Upload 2", IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
- assertTrue(uploadInputStreamEnumeration.hasMoreElements());
- assertEquals("Upload 3", IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
- assertFalse(uploadInputStreamEnumeration.hasMoreElements());
- }
-
- @Test
- public void hasMoreElementsException() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
-
- UploadInfo info2 = new UploadInfo();
- info2.setId(new UploadId(UUID.randomUUID()));
-
- UploadInfo info3 = new UploadInfo();
- info3.setId(new UploadId(UUID.randomUUID()));
-
- when(uploadStorageService.getUploadedBytes(info1.getId()))
- .thenReturn(IOUtils.toInputStream("Upload 1", StandardCharsets.UTF_8));
- when(uploadStorageService.getUploadedBytes(info2.getId()))
- .thenThrow(new IOException("Test"));
- when(uploadStorageService.getUploadedBytes(info3.getId()))
- .thenReturn(IOUtils.toInputStream("Upload 3", StandardCharsets.UTF_8));
-
- UploadInputStreamEnumeration uploadInputStreamEnumeration
- = new UploadInputStreamEnumeration(Arrays.asList(info1, info2, info3), uploadStorageService);
-
- assertTrue(uploadInputStreamEnumeration.hasMoreElements());
- assertEquals("Upload 1", IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
- assertFalse(uploadInputStreamEnumeration.hasMoreElements());
- assertEquals(null, uploadInputStreamEnumeration.nextElement());
- assertFalse(uploadInputStreamEnumeration.hasMoreElements());
- }
-
- @Test
- public void hasMoreElementsNotFound() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
-
- UploadInfo info2 = new UploadInfo();
- info2.setId(new UploadId(UUID.randomUUID()));
-
- UploadInfo info3 = new UploadInfo();
- info3.setId(new UploadId(UUID.randomUUID()));
-
- when(uploadStorageService.getUploadedBytes(info1.getId()))
- .thenReturn(IOUtils.toInputStream("Upload 1", StandardCharsets.UTF_8));
- when(uploadStorageService.getUploadedBytes(info2.getId()))
- .thenReturn(null);
- when(uploadStorageService.getUploadedBytes(info3.getId()))
- .thenReturn(IOUtils.toInputStream("Upload 3", StandardCharsets.UTF_8));
-
- UploadInputStreamEnumeration uploadInputStreamEnumeration
- = new UploadInputStreamEnumeration(Arrays.asList(info1, info2, info3), uploadStorageService);
-
- assertTrue(uploadInputStreamEnumeration.hasMoreElements());
- assertEquals("Upload 1", IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
- assertFalse(uploadInputStreamEnumeration.hasMoreElements());
- assertEquals(null, uploadInputStreamEnumeration.nextElement());
- assertFalse(uploadInputStreamEnumeration.hasMoreElements());
- }
-
- @Test
- public void hasMoreElementsNullElement() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setId(new UploadId(UUID.randomUUID()));
-
- UploadInfo info3 = new UploadInfo();
- info3.setId(new UploadId(UUID.randomUUID()));
-
- when(uploadStorageService.getUploadedBytes(info1.getId()))
- .thenReturn(IOUtils.toInputStream("Upload 1", StandardCharsets.UTF_8));
- when(uploadStorageService.getUploadedBytes(info3.getId()))
- .thenReturn(IOUtils.toInputStream("Upload 3", StandardCharsets.UTF_8));
-
- UploadInputStreamEnumeration uploadInputStreamEnumeration
- = new UploadInputStreamEnumeration(Arrays.asList(info1, null, info3), uploadStorageService);
-
- assertTrue(uploadInputStreamEnumeration.hasMoreElements());
- assertEquals("Upload 1", IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
- assertFalse(uploadInputStreamEnumeration.hasMoreElements());
- assertEquals(null, uploadInputStreamEnumeration.nextElement());
- assertFalse(uploadInputStreamEnumeration.hasMoreElements());
- }
-
- @Test
- public void hasMoreElementsEmptyList() throws Exception {
- UploadInputStreamEnumeration uploadInputStreamEnumeration
- = new UploadInputStreamEnumeration(new LinkedList(), uploadStorageService);
-
- assertFalse(uploadInputStreamEnumeration.hasMoreElements());
- assertEquals(null, uploadInputStreamEnumeration.nextElement());
- assertFalse(uploadInputStreamEnumeration.hasMoreElements());
- }
-}
\ No newline at end of file
+ @Mock private UploadStorageService uploadStorageService;
+
+ @Test
+ public void hasMoreElements() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+
+ UploadInfo info2 = new UploadInfo();
+ info2.setId(new UploadId(UUID.randomUUID()));
+
+ UploadInfo info3 = new UploadInfo();
+ info3.setId(new UploadId(UUID.randomUUID()));
+
+ when(uploadStorageService.getUploadedBytes(info1.getId()))
+ .thenReturn(IOUtils.toInputStream("Upload 1", StandardCharsets.UTF_8));
+ when(uploadStorageService.getUploadedBytes(info2.getId()))
+ .thenReturn(IOUtils.toInputStream("Upload 2", StandardCharsets.UTF_8));
+ when(uploadStorageService.getUploadedBytes(info3.getId()))
+ .thenReturn(IOUtils.toInputStream("Upload 3", StandardCharsets.UTF_8));
+
+ UploadInputStreamEnumeration uploadInputStreamEnumeration =
+ new UploadInputStreamEnumeration(Arrays.asList(info1, info2, info3), uploadStorageService);
+
+ assertTrue(uploadInputStreamEnumeration.hasMoreElements());
+ assertEquals(
+ "Upload 1",
+ IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
+ assertTrue(uploadInputStreamEnumeration.hasMoreElements());
+ assertEquals(
+ "Upload 2",
+ IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
+ assertTrue(uploadInputStreamEnumeration.hasMoreElements());
+ assertEquals(
+ "Upload 3",
+ IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
+ assertFalse(uploadInputStreamEnumeration.hasMoreElements());
+ }
+
+ @Test
+ public void hasMoreElementsException() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+
+ UploadInfo info2 = new UploadInfo();
+ info2.setId(new UploadId(UUID.randomUUID()));
+
+ UploadInfo info3 = new UploadInfo();
+ info3.setId(new UploadId(UUID.randomUUID()));
+
+ when(uploadStorageService.getUploadedBytes(info1.getId()))
+ .thenReturn(IOUtils.toInputStream("Upload 1", StandardCharsets.UTF_8));
+ when(uploadStorageService.getUploadedBytes(info2.getId())).thenThrow(new IOException("Test"));
+ when(uploadStorageService.getUploadedBytes(info3.getId()))
+ .thenReturn(IOUtils.toInputStream("Upload 3", StandardCharsets.UTF_8));
+
+ UploadInputStreamEnumeration uploadInputStreamEnumeration =
+ new UploadInputStreamEnumeration(Arrays.asList(info1, info2, info3), uploadStorageService);
+
+ assertTrue(uploadInputStreamEnumeration.hasMoreElements());
+ assertEquals(
+ "Upload 1",
+ IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
+ assertFalse(uploadInputStreamEnumeration.hasMoreElements());
+ assertEquals(null, uploadInputStreamEnumeration.nextElement());
+ assertFalse(uploadInputStreamEnumeration.hasMoreElements());
+ }
+
+ @Test
+ public void hasMoreElementsNotFound() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+
+ UploadInfo info2 = new UploadInfo();
+ info2.setId(new UploadId(UUID.randomUUID()));
+
+ UploadInfo info3 = new UploadInfo();
+ info3.setId(new UploadId(UUID.randomUUID()));
+
+ when(uploadStorageService.getUploadedBytes(info1.getId()))
+ .thenReturn(IOUtils.toInputStream("Upload 1", StandardCharsets.UTF_8));
+ when(uploadStorageService.getUploadedBytes(info2.getId())).thenReturn(null);
+ when(uploadStorageService.getUploadedBytes(info3.getId()))
+ .thenReturn(IOUtils.toInputStream("Upload 3", StandardCharsets.UTF_8));
+
+ UploadInputStreamEnumeration uploadInputStreamEnumeration =
+ new UploadInputStreamEnumeration(Arrays.asList(info1, info2, info3), uploadStorageService);
+
+ assertTrue(uploadInputStreamEnumeration.hasMoreElements());
+ assertEquals(
+ "Upload 1",
+ IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
+ assertFalse(uploadInputStreamEnumeration.hasMoreElements());
+ assertEquals(null, uploadInputStreamEnumeration.nextElement());
+ assertFalse(uploadInputStreamEnumeration.hasMoreElements());
+ }
+
+ @Test
+ public void hasMoreElementsNullElement() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setId(new UploadId(UUID.randomUUID()));
+
+ UploadInfo info3 = new UploadInfo();
+ info3.setId(new UploadId(UUID.randomUUID()));
+
+ when(uploadStorageService.getUploadedBytes(info1.getId()))
+ .thenReturn(IOUtils.toInputStream("Upload 1", StandardCharsets.UTF_8));
+ when(uploadStorageService.getUploadedBytes(info3.getId()))
+ .thenReturn(IOUtils.toInputStream("Upload 3", StandardCharsets.UTF_8));
+
+ UploadInputStreamEnumeration uploadInputStreamEnumeration =
+ new UploadInputStreamEnumeration(Arrays.asList(info1, null, info3), uploadStorageService);
+
+ assertTrue(uploadInputStreamEnumeration.hasMoreElements());
+ assertEquals(
+ "Upload 1",
+ IOUtils.toString(uploadInputStreamEnumeration.nextElement(), StandardCharsets.UTF_8));
+ assertFalse(uploadInputStreamEnumeration.hasMoreElements());
+ assertEquals(null, uploadInputStreamEnumeration.nextElement());
+ assertFalse(uploadInputStreamEnumeration.hasMoreElements());
+ }
+
+ @Test
+ public void hasMoreElementsEmptyList() throws Exception {
+ UploadInputStreamEnumeration uploadInputStreamEnumeration =
+ new UploadInputStreamEnumeration(new LinkedList(), uploadStorageService);
+
+ assertFalse(uploadInputStreamEnumeration.hasMoreElements());
+ assertEquals(null, uploadInputStreamEnumeration.nextElement());
+ assertFalse(uploadInputStreamEnumeration.hasMoreElements());
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/upload/concatenation/VirtualConcatenationServiceTest.java b/src/test/java/me/desair/tus/server/upload/concatenation/VirtualConcatenationServiceTest.java
index c6676ef..d75b78c 100644
--- a/src/test/java/me/desair/tus/server/upload/concatenation/VirtualConcatenationServiceTest.java
+++ b/src/test/java/me/desair/tus/server/upload/concatenation/VirtualConcatenationServiceTest.java
@@ -12,7 +12,6 @@
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.UUID;
-
import me.desair.tus.server.exception.UploadNotFoundException;
import me.desair.tus.server.upload.UploadId;
import me.desair.tus.server.upload.UploadInfo;
@@ -28,300 +27,318 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class VirtualConcatenationServiceTest {
- @Mock
- private UploadStorageService uploadStorageService;
-
- private VirtualConcatenationService concatenationService;
-
- @Before
- public void setUp() {
- concatenationService = new VirtualConcatenationService(uploadStorageService);
- }
-
- @Test
- public void merge() throws Exception {
- UploadInfo child1 = new UploadInfo();
- child1.setId(new UploadId(UUID.randomUUID()));
- child1.setLength(5L);
- child1.setOffset(5L);
-
- UploadInfo child2 = new UploadInfo();
- child2.setId(new UploadId(UUID.randomUUID()));
- child2.setLength(10L);
- child2.setOffset(10L);
-
- UploadInfo infoParent = new UploadInfo();
- infoParent.setId(new UploadId(UUID.randomUUID()));
- infoParent.setConcatenationPartIds(Arrays.asList(child1.getId().toString(), child2.getId().toString()));
-
- when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child1);
- when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child2);
- when(uploadStorageService.getUploadInfo(infoParent.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(infoParent);
-
- concatenationService.merge(infoParent);
-
- assertThat(infoParent.getLength(), is(15L));
- assertThat(infoParent.getOffset(), is(15L));
- assertThat(infoParent.isUploadInProgress(), is(false));
-
- verify(uploadStorageService, times(1)).update(infoParent);
- }
-
- @Test
- public void mergeNotCompleted() throws Exception {
- UploadInfo child1 = new UploadInfo();
- child1.setId(new UploadId(UUID.randomUUID()));
- child1.setLength(5L);
- child1.setOffset(5L);
-
- UploadInfo child2 = new UploadInfo();
- child2.setId(new UploadId(UUID.randomUUID()));
- child2.setLength(10L);
- child2.setOffset(8L);
-
- UploadInfo infoParent = new UploadInfo();
- infoParent.setId(new UploadId(UUID.randomUUID()));
- infoParent.setConcatenationPartIds(Arrays.asList(child1.getId().toString(), child2.getId().toString()));
-
- when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child1);
- when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child2);
- when(uploadStorageService.getUploadInfo(infoParent.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(infoParent);
-
- concatenationService.merge(infoParent);
-
- assertThat(infoParent.getLength(), is(15L));
- assertThat(infoParent.getOffset(), is(0L));
- assertThat(infoParent.isUploadInProgress(), is(true));
-
- verify(uploadStorageService, times(1)).update(infoParent);
- }
-
- @Test
- public void mergeWithoutLength() throws Exception {
- UploadInfo child1 = new UploadInfo();
- child1.setId(new UploadId(UUID.randomUUID()));
- child1.setLength(null);
- child1.setOffset(5L);
-
- UploadInfo child2 = new UploadInfo();
- child2.setId(new UploadId(UUID.randomUUID()));
- child2.setLength(null);
- child2.setOffset(8L);
-
- UploadInfo infoParent = new UploadInfo();
- infoParent.setId(new UploadId(UUID.randomUUID()));
- infoParent.setConcatenationPartIds(Arrays.asList(child1.getId().toString(), child2.getId().toString()));
-
- when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child1);
- when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child2);
- when(uploadStorageService.getUploadInfo(infoParent.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(infoParent);
-
- concatenationService.merge(infoParent);
-
- assertThat(infoParent.getLength(), is(nullValue()));
- assertThat(infoParent.getOffset(), is(0L));
- assertThat(infoParent.isUploadInProgress(), is(true));
-
- verify(uploadStorageService, never()).update(infoParent);
- }
-
- @Test(expected = UploadNotFoundException.class)
- public void mergeNotFound() throws Exception {
- UploadInfo child1 = new UploadInfo();
- child1.setId(new UploadId(UUID.randomUUID()));
- child1.setLength(5L);
- child1.setOffset(5L);
-
- UploadInfo child2 = new UploadInfo();
- child2.setId(new UploadId(UUID.randomUUID()));
- child2.setLength(10L);
- child2.setOffset(10L);
-
- UploadInfo infoParent = new UploadInfo();
- infoParent.setId(new UploadId(UUID.randomUUID()));
- infoParent.setConcatenationPartIds(Arrays.asList(child1.getId().toString(), child2.getId().toString()));
-
- when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child1);
- when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(null);
- when(uploadStorageService.getUploadInfo(infoParent.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(infoParent);
-
- concatenationService.merge(infoParent);
- }
-
- @Test
- public void mergeWithExpiration() throws Exception {
- UploadInfo child1 = new UploadInfo();
- child1.setId(new UploadId(UUID.randomUUID()));
- child1.setLength(5L);
- child1.setOffset(5L);
-
- UploadInfo child2 = new UploadInfo();
- child2.setId(new UploadId(UUID.randomUUID()));
- child2.setLength(10L);
- child2.setOffset(8L);
-
- UploadInfo infoParent = new UploadInfo();
- infoParent.setId(new UploadId(UUID.randomUUID()));
- infoParent.setConcatenationPartIds(Arrays.asList(child1.getId().toString(), child2.getId().toString()));
-
- when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child1);
- when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child2);
- when(uploadStorageService.getUploadInfo(infoParent.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(infoParent);
-
- when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(500L);
-
- concatenationService.merge(infoParent);
-
- assertThat(infoParent.getLength(), is(15L));
- assertThat(infoParent.getOffset(), is(0L));
- assertThat(infoParent.isUploadInProgress(), is(true));
-
- assertThat(infoParent.getExpirationTimestamp(), is(notNullValue()));
- assertThat(child1.getExpirationTimestamp(), is(notNullValue()));
- //We should not update uploads that are still in progress (as they might still being written)
- assertThat(child2.getExpirationTimestamp(), is(nullValue()));
-
- verify(uploadStorageService, times(1)).update(infoParent);
- verify(uploadStorageService, times(1)).update(child1);
- //We should not update uploads that are still in progress (as they might still being written)
- verify(uploadStorageService, never()).update(child2);
- }
-
- @Test
- public void getUploadsEmptyFinal() throws Exception {
- UploadInfo infoParent = new UploadInfo();
- infoParent.setId(new UploadId(UUID.randomUUID()));
- infoParent.setConcatenationPartIds(null);
-
- when(uploadStorageService.getUploadInfo(infoParent.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(infoParent);
-
- assertThat(concatenationService.getPartialUploads(infoParent), Matchers.empty());
-
- assertThat(infoParent.getLength(), is(nullValue()));
- assertThat(infoParent.getOffset(), is(0L));
- assertThat(infoParent.isUploadInProgress(), is(true));
-
- verify(uploadStorageService, never()).update(infoParent);
- }
-
- @Test
- public void getConcatenatedBytes() throws Exception {
- String upload1 = "This is a ";
- String upload2 = "concatenated upload!";
-
- UploadInfo child1 = new UploadInfo();
- child1.setId(new UploadId(UUID.randomUUID()));
- child1.setLength((long) upload1.getBytes().length);
- child1.setOffset((long) upload1.getBytes().length);
-
- UploadInfo child2 = new UploadInfo();
- child2.setId(new UploadId(UUID.randomUUID()));
- child2.setLength((long) upload2.getBytes().length);
- child2.setOffset((long) upload2.getBytes().length);
-
- UploadInfo infoParent = new UploadInfo();
- infoParent.setId(new UploadId(UUID.randomUUID()));
- infoParent.setConcatenationPartIds(Arrays.asList(child1.getId().toString(), child2.getId().toString()));
-
- when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child1);
- when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child2);
- when(uploadStorageService.getUploadInfo(infoParent.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(infoParent);
-
- when(uploadStorageService.getUploadedBytes(child1.getId()))
- .thenReturn(IOUtils.toInputStream(upload1, StandardCharsets.UTF_8));
- when(uploadStorageService.getUploadedBytes(child2.getId()))
- .thenReturn(IOUtils.toInputStream(upload2, StandardCharsets.UTF_8));
-
- assertThat(IOUtils.toString(concatenationService.getConcatenatedBytes(infoParent), StandardCharsets.UTF_8),
- is("This is a concatenated upload!"));
- }
-
- @Test
- public void getConcatenatedBytesNotComplete() throws Exception {
- String upload1 = "This is a ";
- String upload2 = "concatenated upload!";
-
- UploadInfo child1 = new UploadInfo();
- child1.setId(new UploadId(UUID.randomUUID()));
- child1.setLength((long) upload1.getBytes().length);
- child1.setOffset((long) upload1.getBytes().length - 2);
-
- UploadInfo child2 = new UploadInfo();
- child2.setId(new UploadId(UUID.randomUUID()));
- child2.setLength((long) upload2.getBytes().length);
- child2.setOffset((long) upload2.getBytes().length - 2);
-
- UploadInfo infoParent = new UploadInfo();
- infoParent.setId(new UploadId(UUID.randomUUID()));
- infoParent.setConcatenationPartIds(Arrays.asList(child1.getId().toString(), child2.getId().toString()));
-
- when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child1);
- when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child2);
- when(uploadStorageService.getUploadInfo(infoParent.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(infoParent);
-
- when(uploadStorageService.getUploadedBytes(child1.getId()))
- .thenReturn(IOUtils.toInputStream(upload1, StandardCharsets.UTF_8));
- when(uploadStorageService.getUploadedBytes(child2.getId()))
- .thenReturn(IOUtils.toInputStream(upload2, StandardCharsets.UTF_8));
-
- assertThat(concatenationService.getConcatenatedBytes(infoParent),
- is(nullValue()));
- }
-
- @Test(expected = UploadNotFoundException.class)
- public void getConcatenatedBytesNotFound() throws Exception {
- String upload1 = "This is a ";
- String upload2 = "concatenated upload!";
-
- UploadInfo child1 = new UploadInfo();
- child1.setId(new UploadId(UUID.randomUUID()));
- child1.setLength((long) upload1.getBytes().length);
- child1.setOffset((long) upload1.getBytes().length - 2);
-
- UploadInfo child2 = new UploadInfo();
- child2.setId(new UploadId(UUID.randomUUID()));
- child2.setLength((long) upload2.getBytes().length);
- child2.setOffset((long) upload2.getBytes().length - 2);
-
- UploadInfo infoParent = new UploadInfo();
- infoParent.setId(new UploadId(UUID.randomUUID()));
- infoParent.setConcatenationPartIds(Arrays.asList(child1.getId().toString(), child2.getId().toString()));
-
- when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(child1);
- when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(null);
- when(uploadStorageService.getUploadInfo(infoParent.getId().toString(), infoParent.getOwnerKey()))
- .thenReturn(infoParent);
-
- when(uploadStorageService.getUploadedBytes(child1.getId()))
- .thenReturn(IOUtils.toInputStream(upload1, StandardCharsets.UTF_8));
- when(uploadStorageService.getUploadedBytes(child2.getId()))
- .thenReturn(IOUtils.toInputStream(upload2, StandardCharsets.UTF_8));
-
- concatenationService.getConcatenatedBytes(infoParent);
- }
-
-}
\ No newline at end of file
+ @Mock private UploadStorageService uploadStorageService;
+
+ private VirtualConcatenationService concatenationService;
+
+ @Before
+ public void setUp() {
+ concatenationService = new VirtualConcatenationService(uploadStorageService);
+ }
+
+ @Test
+ public void merge() throws Exception {
+ UploadInfo child1 = new UploadInfo();
+ child1.setId(new UploadId(UUID.randomUUID()));
+ child1.setLength(5L);
+ child1.setOffset(5L);
+
+ UploadInfo child2 = new UploadInfo();
+ child2.setId(new UploadId(UUID.randomUUID()));
+ child2.setLength(10L);
+ child2.setOffset(10L);
+
+ UploadInfo infoParent = new UploadInfo();
+ infoParent.setId(new UploadId(UUID.randomUUID()));
+ infoParent.setConcatenationPartIds(
+ Arrays.asList(child1.getId().toString(), child2.getId().toString()));
+
+ when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child1);
+ when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child2);
+ when(uploadStorageService.getUploadInfo(
+ infoParent.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(infoParent);
+
+ concatenationService.merge(infoParent);
+
+ assertThat(infoParent.getLength(), is(15L));
+ assertThat(infoParent.getOffset(), is(15L));
+ assertThat(infoParent.isUploadInProgress(), is(false));
+
+ verify(uploadStorageService, times(1)).update(infoParent);
+ }
+
+ @Test
+ public void mergeNotCompleted() throws Exception {
+ UploadInfo child1 = new UploadInfo();
+ child1.setId(new UploadId(UUID.randomUUID()));
+ child1.setLength(5L);
+ child1.setOffset(5L);
+
+ UploadInfo child2 = new UploadInfo();
+ child2.setId(new UploadId(UUID.randomUUID()));
+ child2.setLength(10L);
+ child2.setOffset(8L);
+
+ UploadInfo infoParent = new UploadInfo();
+ infoParent.setId(new UploadId(UUID.randomUUID()));
+ infoParent.setConcatenationPartIds(
+ Arrays.asList(child1.getId().toString(), child2.getId().toString()));
+
+ when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child1);
+ when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child2);
+ when(uploadStorageService.getUploadInfo(
+ infoParent.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(infoParent);
+
+ concatenationService.merge(infoParent);
+
+ assertThat(infoParent.getLength(), is(15L));
+ assertThat(infoParent.getOffset(), is(0L));
+ assertThat(infoParent.isUploadInProgress(), is(true));
+
+ verify(uploadStorageService, times(1)).update(infoParent);
+ }
+
+ @Test
+ public void mergeWithoutLength() throws Exception {
+ UploadInfo child1 = new UploadInfo();
+ child1.setId(new UploadId(UUID.randomUUID()));
+ child1.setLength(null);
+ child1.setOffset(5L);
+
+ UploadInfo child2 = new UploadInfo();
+ child2.setId(new UploadId(UUID.randomUUID()));
+ child2.setLength(null);
+ child2.setOffset(8L);
+
+ UploadInfo infoParent = new UploadInfo();
+ infoParent.setId(new UploadId(UUID.randomUUID()));
+ infoParent.setConcatenationPartIds(
+ Arrays.asList(child1.getId().toString(), child2.getId().toString()));
+
+ when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child1);
+ when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child2);
+ when(uploadStorageService.getUploadInfo(
+ infoParent.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(infoParent);
+
+ concatenationService.merge(infoParent);
+
+ assertThat(infoParent.getLength(), is(nullValue()));
+ assertThat(infoParent.getOffset(), is(0L));
+ assertThat(infoParent.isUploadInProgress(), is(true));
+
+ verify(uploadStorageService, never()).update(infoParent);
+ }
+
+ @Test(expected = UploadNotFoundException.class)
+ public void mergeNotFound() throws Exception {
+ UploadInfo child1 = new UploadInfo();
+ child1.setId(new UploadId(UUID.randomUUID()));
+ child1.setLength(5L);
+ child1.setOffset(5L);
+
+ UploadInfo child2 = new UploadInfo();
+ child2.setId(new UploadId(UUID.randomUUID()));
+ child2.setLength(10L);
+ child2.setOffset(10L);
+
+ UploadInfo infoParent = new UploadInfo();
+ infoParent.setId(new UploadId(UUID.randomUUID()));
+ infoParent.setConcatenationPartIds(
+ Arrays.asList(child1.getId().toString(), child2.getId().toString()));
+
+ when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child1);
+ when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(null);
+ when(uploadStorageService.getUploadInfo(
+ infoParent.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(infoParent);
+
+ concatenationService.merge(infoParent);
+ }
+
+ @Test
+ public void mergeWithExpiration() throws Exception {
+ UploadInfo child1 = new UploadInfo();
+ child1.setId(new UploadId(UUID.randomUUID()));
+ child1.setLength(5L);
+ child1.setOffset(5L);
+
+ UploadInfo child2 = new UploadInfo();
+ child2.setId(new UploadId(UUID.randomUUID()));
+ child2.setLength(10L);
+ child2.setOffset(8L);
+
+ UploadInfo infoParent = new UploadInfo();
+ infoParent.setId(new UploadId(UUID.randomUUID()));
+ infoParent.setConcatenationPartIds(
+ Arrays.asList(child1.getId().toString(), child2.getId().toString()));
+
+ when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child1);
+ when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child2);
+ when(uploadStorageService.getUploadInfo(
+ infoParent.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(infoParent);
+
+ when(uploadStorageService.getUploadExpirationPeriod()).thenReturn(500L);
+
+ concatenationService.merge(infoParent);
+
+ assertThat(infoParent.getLength(), is(15L));
+ assertThat(infoParent.getOffset(), is(0L));
+ assertThat(infoParent.isUploadInProgress(), is(true));
+
+ assertThat(infoParent.getExpirationTimestamp(), is(notNullValue()));
+ assertThat(child1.getExpirationTimestamp(), is(notNullValue()));
+ // We should not update uploads that are still in progress (as they might still being
+ // written)
+ assertThat(child2.getExpirationTimestamp(), is(nullValue()));
+
+ verify(uploadStorageService, times(1)).update(infoParent);
+ verify(uploadStorageService, times(1)).update(child1);
+ // We should not update uploads that are still in progress (as they might still being
+ // written)
+ verify(uploadStorageService, never()).update(child2);
+ }
+
+ @Test
+ public void getUploadsEmptyFinal() throws Exception {
+ UploadInfo infoParent = new UploadInfo();
+ infoParent.setId(new UploadId(UUID.randomUUID()));
+ infoParent.setConcatenationPartIds(null);
+
+ when(uploadStorageService.getUploadInfo(
+ infoParent.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(infoParent);
+
+ assertThat(concatenationService.getPartialUploads(infoParent), Matchers.empty());
+
+ assertThat(infoParent.getLength(), is(nullValue()));
+ assertThat(infoParent.getOffset(), is(0L));
+ assertThat(infoParent.isUploadInProgress(), is(true));
+
+ verify(uploadStorageService, never()).update(infoParent);
+ }
+
+ @Test
+ public void getConcatenatedBytes() throws Exception {
+ String upload1 = "This is a ";
+ String upload2 = "concatenated upload!";
+
+ UploadInfo child1 = new UploadInfo();
+ child1.setId(new UploadId(UUID.randomUUID()));
+ child1.setLength((long) upload1.getBytes().length);
+ child1.setOffset((long) upload1.getBytes().length);
+
+ UploadInfo child2 = new UploadInfo();
+ child2.setId(new UploadId(UUID.randomUUID()));
+ child2.setLength((long) upload2.getBytes().length);
+ child2.setOffset((long) upload2.getBytes().length);
+
+ UploadInfo infoParent = new UploadInfo();
+ infoParent.setId(new UploadId(UUID.randomUUID()));
+ infoParent.setConcatenationPartIds(
+ Arrays.asList(child1.getId().toString(), child2.getId().toString()));
+
+ when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child1);
+ when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child2);
+ when(uploadStorageService.getUploadInfo(
+ infoParent.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(infoParent);
+
+ when(uploadStorageService.getUploadedBytes(child1.getId()))
+ .thenReturn(IOUtils.toInputStream(upload1, StandardCharsets.UTF_8));
+ when(uploadStorageService.getUploadedBytes(child2.getId()))
+ .thenReturn(IOUtils.toInputStream(upload2, StandardCharsets.UTF_8));
+
+ assertThat(
+ IOUtils.toString(
+ concatenationService.getConcatenatedBytes(infoParent), StandardCharsets.UTF_8),
+ is("This is a concatenated upload!"));
+ }
+
+ @Test
+ public void getConcatenatedBytesNotComplete() throws Exception {
+ String upload1 = "This is a ";
+ String upload2 = "concatenated upload!";
+
+ UploadInfo child1 = new UploadInfo();
+ child1.setId(new UploadId(UUID.randomUUID()));
+ child1.setLength((long) upload1.getBytes().length);
+ child1.setOffset((long) upload1.getBytes().length - 2);
+
+ UploadInfo child2 = new UploadInfo();
+ child2.setId(new UploadId(UUID.randomUUID()));
+ child2.setLength((long) upload2.getBytes().length);
+ child2.setOffset((long) upload2.getBytes().length - 2);
+
+ UploadInfo infoParent = new UploadInfo();
+ infoParent.setId(new UploadId(UUID.randomUUID()));
+ infoParent.setConcatenationPartIds(
+ Arrays.asList(child1.getId().toString(), child2.getId().toString()));
+
+ when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child1);
+ when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child2);
+ when(uploadStorageService.getUploadInfo(
+ infoParent.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(infoParent);
+
+ when(uploadStorageService.getUploadedBytes(child1.getId()))
+ .thenReturn(IOUtils.toInputStream(upload1, StandardCharsets.UTF_8));
+ when(uploadStorageService.getUploadedBytes(child2.getId()))
+ .thenReturn(IOUtils.toInputStream(upload2, StandardCharsets.UTF_8));
+
+ assertThat(concatenationService.getConcatenatedBytes(infoParent), is(nullValue()));
+ }
+
+ @Test(expected = UploadNotFoundException.class)
+ public void getConcatenatedBytesNotFound() throws Exception {
+ String upload1 = "This is a ";
+ String upload2 = "concatenated upload!";
+
+ UploadInfo child1 = new UploadInfo();
+ child1.setId(new UploadId(UUID.randomUUID()));
+ child1.setLength((long) upload1.getBytes().length);
+ child1.setOffset((long) upload1.getBytes().length - 2);
+
+ UploadInfo child2 = new UploadInfo();
+ child2.setId(new UploadId(UUID.randomUUID()));
+ child2.setLength((long) upload2.getBytes().length);
+ child2.setOffset((long) upload2.getBytes().length - 2);
+
+ UploadInfo infoParent = new UploadInfo();
+ infoParent.setId(new UploadId(UUID.randomUUID()));
+ infoParent.setConcatenationPartIds(
+ Arrays.asList(child1.getId().toString(), child2.getId().toString()));
+
+ when(uploadStorageService.getUploadInfo(child1.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(child1);
+ when(uploadStorageService.getUploadInfo(child2.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(null);
+ when(uploadStorageService.getUploadInfo(
+ infoParent.getId().toString(), infoParent.getOwnerKey()))
+ .thenReturn(infoParent);
+
+ when(uploadStorageService.getUploadedBytes(child1.getId()))
+ .thenReturn(IOUtils.toInputStream(upload1, StandardCharsets.UTF_8));
+ when(uploadStorageService.getUploadedBytes(child2.getId()))
+ .thenReturn(IOUtils.toInputStream(upload2, StandardCharsets.UTF_8));
+
+ concatenationService.getConcatenatedBytes(infoParent);
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/upload/disk/DiskLockingServiceTest.java b/src/test/java/me/desair/tus/server/upload/disk/DiskLockingServiceTest.java
index a8c6b81..97ac75c 100644
--- a/src/test/java/me/desair/tus/server/upload/disk/DiskLockingServiceTest.java
+++ b/src/test/java/me/desair/tus/server/upload/disk/DiskLockingServiceTest.java
@@ -16,7 +16,6 @@
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.util.UUID;
-
import me.desair.tus.server.upload.UploadId;
import me.desair.tus.server.upload.UploadIdFactory;
import me.desair.tus.server.upload.UploadLock;
@@ -35,108 +34,115 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class DiskLockingServiceTest {
- public static final String UPLOAD_URL = "/upload/test";
- private DiskLockingService lockingService;
-
- @Mock
- private UploadIdFactory idFactory;
-
- private static Path storagePath;
-
- @BeforeClass
- public static void setupDataFolder() throws IOException {
- storagePath = Paths.get("target", "tus", "data").toAbsolutePath();
- Files.createDirectories(storagePath);
- }
+ public static final String UPLOAD_URL = "/upload/test";
+ private DiskLockingService lockingService;
- @AfterClass
- public static void destroyDataFolder() throws IOException {
- FileUtils.deleteDirectory(storagePath.toFile());
- }
+ @Mock private UploadIdFactory idFactory;
- @Before
- public void setUp() {
- reset(idFactory);
- when(idFactory.getUploadURI()).thenReturn(UPLOAD_URL);
- when(idFactory.createId()).thenReturn(new UploadId(UUID.randomUUID()));
- when(idFactory.readUploadId(nullable(String.class))).then(new Answer() {
- @Override
- public UploadId answer(InvocationOnMock invocation) throws Throwable {
- return new UploadId(StringUtils.substringAfter(invocation.getArguments()[0].toString(),
- UPLOAD_URL + "/"));
- }
- });
+ private static Path storagePath;
- lockingService = new DiskLockingService(idFactory, storagePath.toString());
- }
+ @BeforeClass
+ public static void setupDataFolder() throws IOException {
+ storagePath = Paths.get("target", "tus", "data").toAbsolutePath();
+ Files.createDirectories(storagePath);
+ }
- @Test
- public void lockUploadByUri() throws Exception {
- UploadLock uploadLock = lockingService.lockUploadByUri("/upload/test/000003f1-a850-49de-af03-997272d834c9");
+ @AfterClass
+ public static void destroyDataFolder() throws IOException {
+ FileUtils.deleteDirectory(storagePath.toFile());
+ }
- assertThat(uploadLock, not(nullValue()));
+ @Before
+ public void setUp() {
+ reset(idFactory);
+ when(idFactory.getUploadURI()).thenReturn(UPLOAD_URL);
+ when(idFactory.createId()).thenReturn(new UploadId(UUID.randomUUID()));
+ when(idFactory.readUploadId(nullable(String.class)))
+ .then(
+ new Answer() {
+ @Override
+ public UploadId answer(InvocationOnMock invocation) throws Throwable {
+ return new UploadId(
+ StringUtils.substringAfter(
+ invocation.getArguments()[0].toString(), UPLOAD_URL + "/"));
+ }
+ });
- uploadLock.release();
- }
+ lockingService = new DiskLockingService(idFactory, storagePath.toString());
+ }
- @Test
- public void isLockedTrue() throws Exception {
- UploadLock uploadLock = lockingService.lockUploadByUri("/upload/test/000003f1-a850-49de-af03-997272d834c9");
+ @Test
+ public void lockUploadByUri() throws Exception {
+ UploadLock uploadLock =
+ lockingService.lockUploadByUri("/upload/test/000003f1-a850-49de-af03-997272d834c9");
- assertThat(lockingService.isLocked(new UploadId("000003f1-a850-49de-af03-997272d834c9")), is(true));
+ assertThat(uploadLock, not(nullValue()));
- uploadLock.release();
- }
+ uploadLock.release();
+ }
- @Test
- public void isLockedFalse() throws Exception {
- UploadLock uploadLock = lockingService.lockUploadByUri("/upload/test/000003f1-a850-49de-af03-997272d834c9");
- uploadLock.release();
+ @Test
+ public void isLockedTrue() throws Exception {
+ UploadLock uploadLock =
+ lockingService.lockUploadByUri("/upload/test/000003f1-a850-49de-af03-997272d834c9");
- assertThat(lockingService.isLocked(new UploadId("000003f1-a850-49de-af03-997272d834c9")), is(false));
- }
+ assertThat(
+ lockingService.isLocked(new UploadId("000003f1-a850-49de-af03-997272d834c9")), is(true));
- @Test
- public void lockUploadNotExists() throws Exception {
- reset(idFactory);
- when(idFactory.readUploadId(nullable(String.class))).thenReturn(null);
+ uploadLock.release();
+ }
- UploadLock uploadLock = lockingService.lockUploadByUri("/upload/test/000003f1-a850-49de-af03-997272d834c9");
+ @Test
+ public void isLockedFalse() throws Exception {
+ UploadLock uploadLock =
+ lockingService.lockUploadByUri("/upload/test/000003f1-a850-49de-af03-997272d834c9");
+ uploadLock.release();
- assertThat(uploadLock, nullValue());
- }
+ assertThat(
+ lockingService.isLocked(new UploadId("000003f1-a850-49de-af03-997272d834c9")), is(false));
+ }
- @Test
- public void cleanupStaleLocks() throws Exception {
- Path locksPath = storagePath.resolve("locks");
+ @Test
+ public void lockUploadNotExists() throws Exception {
+ reset(idFactory);
+ when(idFactory.readUploadId(nullable(String.class))).thenReturn(null);
- String activeLock = "000003f1-a850-49de-af03-997272d834c9";
- UploadLock uploadLock = lockingService.lockUploadByUri("/upload/test/" + activeLock);
+ UploadLock uploadLock =
+ lockingService.lockUploadByUri("/upload/test/000003f1-a850-49de-af03-997272d834c9");
- assertThat(uploadLock, not(nullValue()));
+ assertThat(uploadLock, nullValue());
+ }
- String staleLock = UUID.randomUUID().toString();
- Files.createFile(locksPath.resolve(staleLock));
+ @Test
+ public void cleanupStaleLocks() throws Exception {
+ Path locksPath = storagePath.resolve("locks");
- String recentLock = UUID.randomUUID().toString();
- Files.createFile(locksPath.resolve(recentLock));
+ String activeLock = "000003f1-a850-49de-af03-997272d834c9";
+ UploadLock uploadLock = lockingService.lockUploadByUri("/upload/test/" + activeLock);
- Files.setLastModifiedTime(locksPath.resolve(staleLock),
- FileTime.fromMillis(System.currentTimeMillis() - 20000));
- Files.setLastModifiedTime(locksPath.resolve(activeLock),
- FileTime.fromMillis(System.currentTimeMillis() - 20000));
+ assertThat(uploadLock, not(nullValue()));
- assertTrue(Files.exists(locksPath.resolve(staleLock)));
- assertTrue(Files.exists(locksPath.resolve(activeLock)));
- assertTrue(Files.exists(locksPath.resolve(recentLock)));
+ String staleLock = UUID.randomUUID().toString();
+ Files.createFile(locksPath.resolve(staleLock));
- lockingService.cleanupStaleLocks();
+ String recentLock = UUID.randomUUID().toString();
+ Files.createFile(locksPath.resolve(recentLock));
- assertFalse(Files.exists(locksPath.resolve(staleLock)));
- assertTrue(Files.exists(locksPath.resolve(activeLock)));
- assertTrue(Files.exists(locksPath.resolve(recentLock)));
+ Files.setLastModifiedTime(
+ locksPath.resolve(staleLock), FileTime.fromMillis(System.currentTimeMillis() - 20000));
+ Files.setLastModifiedTime(
+ locksPath.resolve(activeLock), FileTime.fromMillis(System.currentTimeMillis() - 20000));
- uploadLock.release();
- }
+ assertTrue(Files.exists(locksPath.resolve(staleLock)));
+ assertTrue(Files.exists(locksPath.resolve(activeLock)));
+ assertTrue(Files.exists(locksPath.resolve(recentLock)));
-}
\ No newline at end of file
+ lockingService.cleanupStaleLocks();
+
+ assertFalse(Files.exists(locksPath.resolve(staleLock)));
+ assertTrue(Files.exists(locksPath.resolve(activeLock)));
+ assertTrue(Files.exists(locksPath.resolve(recentLock)));
+
+ uploadLock.release();
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/upload/disk/DiskStorageServiceTest.java b/src/test/java/me/desair/tus/server/upload/disk/DiskStorageServiceTest.java
index f9ed2cd..85e59ab 100644
--- a/src/test/java/me/desair/tus/server/upload/disk/DiskStorageServiceTest.java
+++ b/src/test/java/me/desair/tus/server/upload/disk/DiskStorageServiceTest.java
@@ -24,7 +24,6 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
-
import me.desair.tus.server.exception.InvalidUploadOffsetException;
import me.desair.tus.server.exception.UploadNotFoundException;
import me.desair.tus.server.upload.UploadId;
@@ -48,462 +47,473 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class DiskStorageServiceTest {
- public static final String UPLOAD_URL = "/upload/test";
- private DiskStorageService storageService;
-
- @Mock
- private UploadIdFactory idFactory;
-
- @Mock
- private UploadLockingService uploadLockingService;
-
- private static Path storagePath;
-
- @BeforeClass
- public static void setupDataFolder() throws IOException {
- storagePath = Paths.get("target", "tus", "data").toAbsolutePath();
- Files.createDirectories(storagePath);
- }
-
- @AfterClass
- public static void destroyDataFolder() throws IOException {
- FileUtils.deleteDirectory(storagePath.toFile());
- }
-
- @Before
- public void setUp() {
- reset(idFactory);
- when(idFactory.getUploadURI()).thenReturn(UPLOAD_URL);
- when(idFactory.createId()).thenReturn(new UploadId(UUID.randomUUID()));
- when(idFactory.readUploadId(nullable(String.class))).then(new Answer() {
- @Override
- public UploadId answer(InvocationOnMock invocation) throws Throwable {
- return new UploadId(StringUtils.substringAfter(invocation.getArguments()[0].toString(),
- UPLOAD_URL + "/"));
- }
- });
-
- storageService = new DiskStorageService(idFactory, storagePath.toString());
- }
-
- @Test
- public void getMaxUploadSize() throws Exception {
- storageService.setMaxUploadSize(null);
- assertThat(storageService.getMaxUploadSize(), is(0L));
-
- storageService.setMaxUploadSize(0L);
- assertThat(storageService.getMaxUploadSize(), is(0L));
-
- storageService.setMaxUploadSize(-10L);
- assertThat(storageService.getMaxUploadSize(), is(0L));
-
- storageService.setMaxUploadSize(372036854775807L);
- assertThat(storageService.getMaxUploadSize(), is(372036854775807L));
- }
-
- @Test
- public void getUploadURI() throws Exception {
- assertThat(storageService.getUploadURI(), is(UPLOAD_URL));
- }
-
- @Test
- public void create() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setLength(10L);
- info.setEncodedMetadata("Encoded Metadata");
-
- info = storageService.create(info, null);
-
- assertThat(info.getId(), is(notNullValue()));
- assertThat(info.getOffset(), is(0L));
- assertThat(info.getLength(), is(10L));
- assertThat(info.getEncodedMetadata(), is("Encoded Metadata"));
-
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- }
-
- @Test
- public void getUploadInfoById() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setLength(10L);
- info.setEncodedMetadata("Encoded Metadata");
-
- info = storageService.create(info, "John");
-
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
-
- UploadInfo readInfo = storageService.getUploadInfo(info.getId());
-
- assertTrue(readInfo != info);
- assertThat(readInfo.getId(), is(info.getId()));
- assertThat(readInfo.getOffset(), is(0L));
- assertThat(readInfo.getLength(), is(10L));
- assertThat(readInfo.getEncodedMetadata(), is("Encoded Metadata"));
- assertThat(readInfo.getCreationTimestamp(), is(info.getCreationTimestamp()));
- assertThat(readInfo.getUploadType(), is(info.getUploadType()));
- assertThat(readInfo.getOwnerKey(), is(info.getOwnerKey()));
- }
-
- @Test
- public void getUploadInfoByFakeId() throws Exception {
- UploadInfo readInfo = storageService.getUploadInfo(new UploadId(UUID.randomUUID()));
- assertThat(readInfo, is(nullValue()));
- }
-
- @Test
- public void getUploadInfoByUrl() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setLength(10L);
- info.setEncodedMetadata("Encoded Metadata");
+ public static final String UPLOAD_URL = "/upload/test";
+ private DiskStorageService storageService;
+
+ @Mock private UploadIdFactory idFactory;
+
+ @Mock private UploadLockingService uploadLockingService;
+
+ private static Path storagePath;
+
+ @BeforeClass
+ public static void setupDataFolder() throws IOException {
+ storagePath = Paths.get("target", "tus", "data").toAbsolutePath();
+ Files.createDirectories(storagePath);
+ }
+
+ @AfterClass
+ public static void destroyDataFolder() throws IOException {
+ FileUtils.deleteDirectory(storagePath.toFile());
+ }
+
+ @Before
+ public void setUp() {
+ reset(idFactory);
+ when(idFactory.getUploadURI()).thenReturn(UPLOAD_URL);
+ when(idFactory.createId()).thenReturn(new UploadId(UUID.randomUUID()));
+ when(idFactory.readUploadId(nullable(String.class)))
+ .then(
+ new Answer() {
+ @Override
+ public UploadId answer(InvocationOnMock invocation) throws Throwable {
+ return new UploadId(
+ StringUtils.substringAfter(
+ invocation.getArguments()[0].toString(), UPLOAD_URL + "/"));
+ }
+ });
+
+ storageService = new DiskStorageService(idFactory, storagePath.toString());
+ }
+
+ @Test
+ public void getMaxUploadSize() throws Exception {
+ storageService.setMaxUploadSize(null);
+ assertThat(storageService.getMaxUploadSize(), is(0L));
+
+ storageService.setMaxUploadSize(0L);
+ assertThat(storageService.getMaxUploadSize(), is(0L));
+
+ storageService.setMaxUploadSize(-10L);
+ assertThat(storageService.getMaxUploadSize(), is(0L));
+
+ storageService.setMaxUploadSize(372036854775807L);
+ assertThat(storageService.getMaxUploadSize(), is(372036854775807L));
+ }
- info = storageService.create(info, null);
+ @Test
+ public void getUploadURI() throws Exception {
+ assertThat(storageService.getUploadURI(), is(UPLOAD_URL));
+ }
+
+ @Test
+ public void create() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setLength(10L);
+ info.setEncodedMetadata("Encoded Metadata");
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
-
- UploadInfo readInfo = storageService.getUploadInfo(UPLOAD_URL + "/" + info.getId(), null);
-
- assertTrue(readInfo != info);
- assertThat(readInfo.getId(), is(info.getId()));
- assertThat(readInfo.getOffset(), is(0L));
- assertThat(readInfo.getLength(), is(10L));
- assertThat(readInfo.getEncodedMetadata(), is("Encoded Metadata"));
- }
+ info = storageService.create(info, null);
+
+ assertThat(info.getId(), is(notNullValue()));
+ assertThat(info.getOffset(), is(0L));
+ assertThat(info.getLength(), is(10L));
+ assertThat(info.getEncodedMetadata(), is("Encoded Metadata"));
+
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ }
+
+ @Test
+ public void getUploadInfoById() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setLength(10L);
+ info.setEncodedMetadata("Encoded Metadata");
+
+ info = storageService.create(info, "John");
+
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+
+ UploadInfo readInfo = storageService.getUploadInfo(info.getId());
+
+ assertTrue(readInfo != info);
+ assertThat(readInfo.getId(), is(info.getId()));
+ assertThat(readInfo.getOffset(), is(0L));
+ assertThat(readInfo.getLength(), is(10L));
+ assertThat(readInfo.getEncodedMetadata(), is("Encoded Metadata"));
+ assertThat(readInfo.getCreationTimestamp(), is(info.getCreationTimestamp()));
+ assertThat(readInfo.getUploadType(), is(info.getUploadType()));
+ assertThat(readInfo.getOwnerKey(), is(info.getOwnerKey()));
+ }
+
+ @Test
+ public void getUploadInfoByFakeId() throws Exception {
+ UploadInfo readInfo = storageService.getUploadInfo(new UploadId(UUID.randomUUID()));
+ assertThat(readInfo, is(nullValue()));
+ }
+
+ @Test
+ public void getUploadInfoByUrl() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setLength(10L);
+ info.setEncodedMetadata("Encoded Metadata");
+
+ info = storageService.create(info, null);
+
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+
+ UploadInfo readInfo = storageService.getUploadInfo(UPLOAD_URL + "/" + info.getId(), null);
+
+ assertTrue(readInfo != info);
+ assertThat(readInfo.getId(), is(info.getId()));
+ assertThat(readInfo.getOffset(), is(0L));
+ assertThat(readInfo.getLength(), is(10L));
+ assertThat(readInfo.getEncodedMetadata(), is("Encoded Metadata"));
+ }
+
+ @Test
+ public void getUploadInfoOtherOwner() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setLength(10L);
+ info.setEncodedMetadata("Encoded Metadata");
+
+ info = storageService.create(info, "foo");
+
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- @Test
- public void getUploadInfoOtherOwner() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setLength(10L);
- info.setEncodedMetadata("Encoded Metadata");
+ UploadInfo readInfo = storageService.getUploadInfo(UPLOAD_URL + "/" + info.getId(), "foo");
- info = storageService.create(info, "foo");
+ assertTrue(readInfo != info);
+ assertThat(readInfo.getId(), is(info.getId()));
+ assertThat(readInfo.getOffset(), is(0L));
+ assertThat(readInfo.getLength(), is(10L));
+ assertThat(readInfo.getEncodedMetadata(), is("Encoded Metadata"));
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ assertThat(
+ storageService.getUploadInfo(UPLOAD_URL + "/" + info.getId(), "bar"), is(nullValue()));
+ }
- UploadInfo readInfo = storageService.getUploadInfo(UPLOAD_URL + "/" + info.getId(), "foo");
+ @Test
+ public void update() throws Exception {
+ UploadInfo info1 = new UploadInfo();
+ info1.setLength(10L);
+ info1.setEncodedMetadata("Encoded Metadata");
- assertTrue(readInfo != info);
- assertThat(readInfo.getId(), is(info.getId()));
- assertThat(readInfo.getOffset(), is(0L));
- assertThat(readInfo.getLength(), is(10L));
- assertThat(readInfo.getEncodedMetadata(), is("Encoded Metadata"));
+ info1 = storageService.create(info1, null);
- assertThat(storageService.getUploadInfo(UPLOAD_URL + "/" + info.getId(), "bar"), is(nullValue()));
- }
+ assertTrue(Files.exists(getUploadInfoPath(info1.getId())));
- @Test
- public void update() throws Exception {
- UploadInfo info1 = new UploadInfo();
- info1.setLength(10L);
- info1.setEncodedMetadata("Encoded Metadata");
+ UploadInfo info2 = new UploadInfo();
+ info2.setId(info1.getId());
+ info2.setLength(10L);
+ info2.setOffset(8L);
+ info2.setEncodedMetadata("Updated Encoded Metadata");
- info1 = storageService.create(info1, null);
+ storageService.update(info2);
- assertTrue(Files.exists(getUploadInfoPath(info1.getId())));
+ UploadInfo readInfo = storageService.getUploadInfo(info1.getId());
- UploadInfo info2 = new UploadInfo();
- info2.setId(info1.getId());
- info2.setLength(10L);
- info2.setOffset(8L);
- info2.setEncodedMetadata("Updated Encoded Metadata");
+ assertTrue(readInfo != info1);
+ assertTrue(readInfo != info2);
+ assertThat(info2.getId(), is(info1.getId()));
+ assertThat(readInfo.getId(), is(info1.getId()));
+ assertThat(readInfo.getOffset(), is(8L));
+ assertThat(readInfo.getLength(), is(10L));
+ assertThat(readInfo.getEncodedMetadata(), is("Updated Encoded Metadata"));
+ }
- storageService.update(info2);
+ @Test
+ public void append() throws Exception {
+ String part1 = "This is part 1";
+ String part2 = "This is the second part of my upload";
- UploadInfo readInfo = storageService.getUploadInfo(info1.getId());
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength((long) (part1.getBytes().length + part2.getBytes().length));
+ info.setEncodedMetadata("Encoded Metadata");
- assertTrue(readInfo != info1);
- assertTrue(readInfo != info2);
- assertThat(info2.getId(), is(info1.getId()));
- assertThat(readInfo.getId(), is(info1.getId()));
- assertThat(readInfo.getOffset(), is(8L));
- assertThat(readInfo.getLength(), is(10L));
- assertThat(readInfo.getEncodedMetadata(), is("Updated Encoded Metadata"));
- }
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- @Test
- public void append() throws Exception {
- String part1 = "This is part 1";
- String part2 = "This is the second part of my upload";
+ // Write the first part of the upload
+ storageService.append(info, IOUtils.toInputStream(part1, StandardCharsets.UTF_8));
+ assertThat(new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is(part1));
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength((long) (part1.getBytes().length + part2.getBytes().length));
- info.setEncodedMetadata("Encoded Metadata");
+ UploadInfo readInfo = storageService.getUploadInfo(info.getId());
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ assertThat(readInfo.getId(), is(info.getId()));
+ assertThat(readInfo.getOffset(), is((long) part1.getBytes().length));
+ assertThat(readInfo.getLength(), is(info.getLength()));
+ assertThat(readInfo.getEncodedMetadata(), is("Encoded Metadata"));
- //Write the first part of the upload
- storageService.append(info, IOUtils.toInputStream(part1, StandardCharsets.UTF_8));
- assertThat(new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is(part1));
+ // Write the second part of the upload
+ storageService.append(info, IOUtils.toInputStream(part2, StandardCharsets.UTF_8));
+ assertThat(new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is(part1 + part2));
- UploadInfo readInfo = storageService.getUploadInfo(info.getId());
+ readInfo = storageService.getUploadInfo(info.getId());
- assertThat(readInfo.getId(), is(info.getId()));
- assertThat(readInfo.getOffset(), is((long) part1.getBytes().length));
- assertThat(readInfo.getLength(), is(info.getLength()));
- assertThat(readInfo.getEncodedMetadata(), is("Encoded Metadata"));
+ assertThat(readInfo.getId(), is(info.getId()));
+ assertThat(readInfo.getOffset(), is(info.getLength()));
+ assertThat(readInfo.getLength(), is(info.getLength()));
+ assertThat(readInfo.getEncodedMetadata(), is("Encoded Metadata"));
+ }
- //Write the second part of the upload
- storageService.append(info, IOUtils.toInputStream(part2, StandardCharsets.UTF_8));
- assertThat(new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is(part1 + part2));
+ @Test
+ public void appendExceedingMaxSingleUpload() throws Exception {
+ String content = "This is an upload that is too large";
- readInfo = storageService.getUploadInfo(info.getId());
+ storageService.setMaxUploadSize(17L);
- assertThat(readInfo.getId(), is(info.getId()));
- assertThat(readInfo.getOffset(), is(info.getLength()));
- assertThat(readInfo.getLength(), is(info.getLength()));
- assertThat(readInfo.getEncodedMetadata(), is("Encoded Metadata"));
- }
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength(17L);
- @Test
- public void appendExceedingMaxSingleUpload() throws Exception {
- String content = "This is an upload that is too large";
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- storageService.setMaxUploadSize(17L);
+ // Write the content of the upload
+ storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength(17L);
+ // The storage service should protect itself an only write until the maximum number of bytes
+ // allowed
+ assertThat(
+ new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is("This is an upload"));
+ }
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ @Test
+ public void appendExceedingMaxMultiUpload() throws Exception {
+ String part1 = "This is an ";
+ String part2 = "upload that is too large";
+
+ storageService.setMaxUploadSize(17L);
- //Write the content of the upload
- storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength(17L);
- //The storage service should protect itself an only write until the maximum number of bytes allowed
- assertThat(new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is("This is an upload"));
- }
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- @Test
- public void appendExceedingMaxMultiUpload() throws Exception {
- String part1 = "This is an ";
- String part2 = "upload that is too large";
+ // Write the content of the upload in two parts
+ storageService.append(info, IOUtils.toInputStream(part1, StandardCharsets.UTF_8));
+ info = storageService.getUploadInfo(info.getId());
+ storageService.append(info, IOUtils.toInputStream(part2, StandardCharsets.UTF_8));
- storageService.setMaxUploadSize(17L);
+ // The storage service should protect itself an only write until the maximum number of bytes
+ // allowed
+ assertThat(
+ new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is("This is an upload"));
+ }
+
+ @Test(expected = UploadNotFoundException.class)
+ public void appendOnFakeUpload() throws Exception {
+ String content = "This upload was not created before";
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength(17L);
+ // Create our fake upload
+ UploadInfo info = new UploadInfo();
+ info.setId(new UploadId(UUID.randomUUID()));
+ info.setLength((long) (content.getBytes().length));
+
+ // Write the content of the upload
+ storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+ }
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ @Test(expected = InvalidUploadOffsetException.class)
+ public void appendOnInvalidOffset() throws Exception {
+ String content = "This is an upload that is too large";
- //Write the content of the upload in two parts
- storageService.append(info, IOUtils.toInputStream(part1, StandardCharsets.UTF_8));
- info = storageService.getUploadInfo(info.getId());
- storageService.append(info, IOUtils.toInputStream(part2, StandardCharsets.UTF_8));
+ storageService.setMaxUploadSize(17L);
- //The storage service should protect itself an only write until the maximum number of bytes allowed
- assertThat(new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is("This is an upload"));
- }
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength(17L);
- @Test(expected = UploadNotFoundException.class)
- public void appendOnFakeUpload() throws Exception {
- String content = "This upload was not created before";
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- //Create our fake upload
- UploadInfo info = new UploadInfo();
- info.setId(new UploadId(UUID.randomUUID()));
- info.setLength((long) (content.getBytes().length));
+ info.setOffset(3L);
+ storageService.update(info);
- //Write the content of the upload
- storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
- }
+ // Write the content of the upload
+ storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+ }
- @Test(expected = InvalidUploadOffsetException.class)
- public void appendOnInvalidOffset() throws Exception {
- String content = "This is an upload that is too large";
+ @Test
+ public void appendInterrupted() throws Exception {
+ String content = "This is an upload that will be interrupted";
- storageService.setMaxUploadSize(17L);
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength((long) content.getBytes().length);
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength(17L);
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ InputStream exceptionStream = mock(InputStream.class);
+ doThrow(new RuntimeException())
+ .when(exceptionStream)
+ .read(org.mockito.Mockito.any(byte[].class), anyInt(), anyInt());
- info.setOffset(3L);
- storageService.update(info);
+ InputStream sequenceStream =
+ new SequenceInputStream(
+ IOUtils.toInputStream(content, StandardCharsets.UTF_8), exceptionStream);
- //Write the content of the upload
- storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+ try {
+ // Write the content of the upload
+ storageService.append(info, sequenceStream);
+ fail();
+ } catch (Exception ex) {
+ // ignore
}
- @Test
- public void appendInterrupted() throws Exception {
- String content = "This is an upload that will be interrupted";
+ info = storageService.getUploadInfo(info.getId());
+ assertThat(new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is(content));
+ assertThat(info.getOffset(), is((long) content.getBytes().length));
+ }
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength((long) content.getBytes().length);
+ @Test
+ public void testRemoveLastNumberOfBytes() throws Exception {
+ String content = "This is an upload that will be truncated";
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength(50L);
- InputStream exceptionStream = mock(InputStream.class);
- doThrow(new RuntimeException()).when(exceptionStream)
- .read(org.mockito.Mockito.any(byte[].class), anyInt(), anyInt());
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- InputStream sequenceStream = new SequenceInputStream(IOUtils.toInputStream(content, StandardCharsets.UTF_8),
- exceptionStream);
+ // Write the content of the upload
+ storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
- try {
- //Write the content of the upload
- storageService.append(info, sequenceStream);
- fail();
- } catch (Exception ex) {
- //ignore
- }
+ // Now truncate
+ storageService.removeLastNumberOfBytes(info, 23);
- info = storageService.getUploadInfo(info.getId());
- assertThat(new String(Files.readAllBytes(getUploadDataPath(info.getId()))),
- is(content));
- assertThat(info.getOffset(), is((long) content.getBytes().length));
- }
+ assertThat(
+ new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is("This is an upload"));
+ }
- @Test
- public void testRemoveLastNumberOfBytes() throws Exception {
- String content = "This is an upload that will be truncated";
+ @Test
+ public void getUploadedBytes() throws Exception {
+ String content = "This is the content of my upload";
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength(50L);
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength((long) content.getBytes().length);
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- //Write the content of the upload
- storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+ // Write the content of the upload
+ storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+ assertTrue(Files.exists(getUploadDataPath(info.getId())));
- //Now truncate
- storageService.removeLastNumberOfBytes(info, 23);
+ try (InputStream uploadedBytes =
+ storageService.getUploadedBytes(UPLOAD_URL + "/" + info.getId(), null)) {
- assertThat(new String(Files.readAllBytes(getUploadDataPath(info.getId()))), is("This is an upload"));
+ assertThat(
+ IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
+ is("This is the content of my upload"));
}
+ }
- @Test
- public void getUploadedBytes() throws Exception {
- String content = "This is the content of my upload";
+ @Test
+ public void copyUploadedBytes() throws Exception {
+ String content = "This is the content of my upload";
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength((long) content.getBytes().length);
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength((long) content.getBytes().length);
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- //Write the content of the upload
- storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
- assertTrue(Files.exists(getUploadDataPath(info.getId())));
+ // Write the content of the upload
+ storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+ assertTrue(Files.exists(getUploadDataPath(info.getId())));
- try (InputStream uploadedBytes = storageService.getUploadedBytes(UPLOAD_URL + "/" + info.getId(), null)) {
-
- assertThat(IOUtils.toString(uploadedBytes, StandardCharsets.UTF_8),
- is("This is the content of my upload"));
- }
+ try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
+ storageService.copyUploadTo(info, output);
+ assertThat(
+ new String(output.toByteArray(), StandardCharsets.UTF_8),
+ is("This is the content of my upload"));
}
+ }
- @Test
- public void copyUploadedBytes() throws Exception {
- String content = "This is the content of my upload";
+ @Test
+ public void terminateCompletedUpload() throws Exception {
+ String content = "This is the content of my upload";
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength((long) content.getBytes().length);
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength((long) content.getBytes().length);
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- //Write the content of the upload
- storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
- assertTrue(Files.exists(getUploadDataPath(info.getId())));
+ // Write the content of the upload
+ storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+ assertTrue(Files.exists(getUploadDataPath(info.getId())));
- try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
- storageService.copyUploadTo(info, output);
- assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8),
- is("This is the content of my upload"));
- }
- }
+ // Now delete the upload and check the files are gone
+ storageService.terminateUpload(info);
+ assertFalse(Files.exists(getUploadInfoPath(info.getId())));
+ assertFalse(Files.exists(getUploadDataPath(info.getId())));
+ assertFalse(Files.exists(getStoragePath(info.getId())));
+ }
- @Test
- public void terminateCompletedUpload() throws Exception {
- String content = "This is the content of my upload";
+ @Test
+ public void terminateInProgressUpload() throws Exception {
+ String content = "This is the content of my upload";
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength((long) content.getBytes().length);
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength((long) content.getBytes().length + 20);
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- //Write the content of the upload
- storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
- assertTrue(Files.exists(getUploadDataPath(info.getId())));
+ // Write the content of the upload
+ storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+ assertTrue(Files.exists(getUploadDataPath(info.getId())));
- //Now delete the upload and check the files are gone
- storageService.terminateUpload(info);
- assertFalse(Files.exists(getUploadInfoPath(info.getId())));
- assertFalse(Files.exists(getUploadDataPath(info.getId())));
- assertFalse(Files.exists(getStoragePath(info.getId())));
- }
+ // Now delete the upload and check the files are gone
+ storageService.terminateUpload(info);
+ assertFalse(Files.exists(getUploadInfoPath(info.getId())));
+ assertFalse(Files.exists(getUploadDataPath(info.getId())));
+ assertFalse(Files.exists(getStoragePath(info.getId())));
- @Test
- public void terminateInProgressUpload() throws Exception {
- String content = "This is the content of my upload";
+ // Call with null should not result in an error
+ storageService.terminateUpload(null);
+ }
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength((long) content.getBytes().length + 20);
+ @Test
+ public void cleanupExpiredUploads() throws Exception {
+ when(uploadLockingService.isLocked(any(UploadId.class))).thenReturn(false);
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
+ String content = "This is the content of my upload";
- //Write the content of the upload
- storageService.append(info, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
- assertTrue(Files.exists(getUploadDataPath(info.getId())));
+ // Create our upload with the correct length
+ UploadInfo info = new UploadInfo();
+ info.setLength((long) content.getBytes().length + 20);
+ info.updateExpiration(100L);
- //Now delete the upload and check the files are gone
- storageService.terminateUpload(info);
- assertFalse(Files.exists(getUploadInfoPath(info.getId())));
- assertFalse(Files.exists(getUploadDataPath(info.getId())));
- assertFalse(Files.exists(getStoragePath(info.getId())));
+ info = storageService.create(info, null);
+ assertTrue(Files.exists(getUploadInfoPath(info.getId())));
- //Call with null should not result in an error
- storageService.terminateUpload(null);
- }
+ Utils.sleep(500L);
+ storageService.cleanupExpiredUploads(uploadLockingService);
- @Test
- public void cleanupExpiredUploads() throws Exception {
- when(uploadLockingService.isLocked(any(UploadId.class))).thenReturn(false);
+ assertFalse(Files.exists(getUploadInfoPath(info.getId())));
+ assertFalse(Files.exists(getStoragePath(info.getId())));
+ }
- String content = "This is the content of my upload";
+ private Path getUploadInfoPath(UploadId id) {
+ return getStoragePath(id).resolve("info");
+ }
- //Create our upload with the correct length
- UploadInfo info = new UploadInfo();
- info.setLength((long) content.getBytes().length + 20);
- info.updateExpiration(100L);
+ private Path getUploadDataPath(UploadId id) {
+ return getStoragePath(id).resolve("data");
+ }
- info = storageService.create(info, null);
- assertTrue(Files.exists(getUploadInfoPath(info.getId())));
-
- Utils.sleep(500L);
- storageService.cleanupExpiredUploads(uploadLockingService);
-
- assertFalse(Files.exists(getUploadInfoPath(info.getId())));
- assertFalse(Files.exists(getStoragePath(info.getId())));
- }
-
- private Path getUploadInfoPath(UploadId id) {
- return getStoragePath(id).resolve("info");
- }
-
- private Path getUploadDataPath(UploadId id) {
- return getStoragePath(id).resolve("data");
- }
-
- private Path getStoragePath(UploadId id) {
- return storagePath.resolve("uploads").resolve(id.toString());
- }
-}
\ No newline at end of file
+ private Path getStoragePath(UploadId id) {
+ return storagePath.resolve("uploads").resolve(id.toString());
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/upload/disk/ExpiredUploadFilterTest.java b/src/test/java/me/desair/tus/server/upload/disk/ExpiredUploadFilterTest.java
index e10cb6b..7d0f878 100644
--- a/src/test/java/me/desair/tus/server/upload/disk/ExpiredUploadFilterTest.java
+++ b/src/test/java/me/desair/tus/server/upload/disk/ExpiredUploadFilterTest.java
@@ -10,7 +10,6 @@
import java.nio.file.Paths;
import java.text.ParseException;
import java.util.UUID;
-
import me.desair.tus.server.upload.UploadId;
import me.desair.tus.server.upload.UploadInfo;
import me.desair.tus.server.upload.UploadLockingService;
@@ -24,106 +23,105 @@
@RunWith(MockitoJUnitRunner.Silent.class)
public class ExpiredUploadFilterTest {
- @Mock
- private DiskStorageService diskStorageService;
-
- @Mock
- private UploadLockingService uploadLockingService;
-
- private ExpiredUploadFilter uploadFilter;
-
- @Before
- public void setUp() {
- uploadFilter = new ExpiredUploadFilter(diskStorageService, uploadLockingService);
- }
-
- @Test
- public void accept() throws Exception {
- UploadInfo info = createExpiredUploadInfo();
- info.setId(new UploadId(UUID.randomUUID()));
- info.setOffset(2L);
- info.setLength(10L);
- info.updateExpiration(100L);
-
- when(diskStorageService.getUploadInfo(eq(info.getId()))).thenReturn(info);
- when(uploadLockingService.isLocked(eq(info.getId()))).thenReturn(false);
-
- assertTrue(uploadFilter.accept(Paths.get(info.getId().toString())));
- }
-
- @Test
- public void acceptNotFound() throws Exception {
- when(diskStorageService.getUploadInfo(any(UploadId.class))).thenReturn(null);
- when(uploadLockingService.isLocked(any(UploadId.class))).thenReturn(false);
-
- assertFalse(uploadFilter.accept(Paths.get(UUID.randomUUID().toString())));
- }
-
- @Test
- public void acceptCompletedUpload() throws Exception {
- UploadInfo info = createExpiredUploadInfo();
- info.setId(new UploadId(UUID.randomUUID()));
- info.setOffset(10L);
- info.setLength(10L);
- info.updateExpiration(100L);
-
- when(diskStorageService.getUploadInfo(eq(info.getId()))).thenReturn(info);
- when(uploadLockingService.isLocked(eq(info.getId()))).thenReturn(false);
-
- //Completed uploads also expire
- assertTrue(uploadFilter.accept(Paths.get(info.getId().toString())));
- }
-
- @Test
- public void acceptInProgressButNotExpired() throws Exception {
- UploadInfo info = new UploadInfo();
- info.setId(new UploadId(UUID.randomUUID()));
- info.setOffset(2L);
- info.setLength(10L);
- info.updateExpiration(172800000L);
-
- when(diskStorageService.getUploadInfo(eq(info.getId()))).thenReturn(info);
- when(uploadLockingService.isLocked(eq(info.getId()))).thenReturn(false);
-
- assertFalse(uploadFilter.accept(Paths.get(info.getId().toString())));
- }
-
- @Test
- public void acceptLocked() throws Exception {
- UploadInfo info = createExpiredUploadInfo();
- info.setId(new UploadId(UUID.randomUUID()));
- info.setOffset(8L);
- info.setLength(10L);
- info.updateExpiration(100L);
-
- when(diskStorageService.getUploadInfo(eq(info.getId()))).thenReturn(info);
- when(uploadLockingService.isLocked(eq(info.getId()))).thenReturn(true);
-
- assertFalse(uploadFilter.accept(Paths.get(info.getId().toString())));
- }
-
- @Test
- public void acceptException() throws Exception {
- UploadInfo info = createExpiredUploadInfo();
- info.setId(new UploadId(UUID.randomUUID()));
- info.setOffset(8L);
- info.setLength(10L);
- info.updateExpiration(100L);
-
- when(diskStorageService.getUploadInfo(eq(info.getId()))).thenThrow(new IOException());
- when(uploadLockingService.isLocked(eq(info.getId()))).thenReturn(false);
-
- assertFalse(uploadFilter.accept(Paths.get(info.getId().toString())));
- }
-
- private UploadInfo createExpiredUploadInfo() throws ParseException {
- final long time = DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse("2018-01-20T10:43:11").getTime();
-
- return new UploadInfo() {
- @Override
- protected long getCurrentTime() {
- return getExpirationTimestamp() == null ? time : time + 10000L;
- }
- };
- }
-}
\ No newline at end of file
+ @Mock private DiskStorageService diskStorageService;
+
+ @Mock private UploadLockingService uploadLockingService;
+
+ private ExpiredUploadFilter uploadFilter;
+
+ @Before
+ public void setUp() {
+ uploadFilter = new ExpiredUploadFilter(diskStorageService, uploadLockingService);
+ }
+
+ @Test
+ public void accept() throws Exception {
+ UploadInfo info = createExpiredUploadInfo();
+ info.setId(new UploadId(UUID.randomUUID()));
+ info.setOffset(2L);
+ info.setLength(10L);
+ info.updateExpiration(100L);
+
+ when(diskStorageService.getUploadInfo(eq(info.getId()))).thenReturn(info);
+ when(uploadLockingService.isLocked(eq(info.getId()))).thenReturn(false);
+
+ assertTrue(uploadFilter.accept(Paths.get(info.getId().toString())));
+ }
+
+ @Test
+ public void acceptNotFound() throws Exception {
+ when(diskStorageService.getUploadInfo(any(UploadId.class))).thenReturn(null);
+ when(uploadLockingService.isLocked(any(UploadId.class))).thenReturn(false);
+
+ assertFalse(uploadFilter.accept(Paths.get(UUID.randomUUID().toString())));
+ }
+
+ @Test
+ public void acceptCompletedUpload() throws Exception {
+ UploadInfo info = createExpiredUploadInfo();
+ info.setId(new UploadId(UUID.randomUUID()));
+ info.setOffset(10L);
+ info.setLength(10L);
+ info.updateExpiration(100L);
+
+ when(diskStorageService.getUploadInfo(eq(info.getId()))).thenReturn(info);
+ when(uploadLockingService.isLocked(eq(info.getId()))).thenReturn(false);
+
+ // Completed uploads also expire
+ assertTrue(uploadFilter.accept(Paths.get(info.getId().toString())));
+ }
+
+ @Test
+ public void acceptInProgressButNotExpired() throws Exception {
+ UploadInfo info = new UploadInfo();
+ info.setId(new UploadId(UUID.randomUUID()));
+ info.setOffset(2L);
+ info.setLength(10L);
+ info.updateExpiration(172800000L);
+
+ when(diskStorageService.getUploadInfo(eq(info.getId()))).thenReturn(info);
+ when(uploadLockingService.isLocked(eq(info.getId()))).thenReturn(false);
+
+ assertFalse(uploadFilter.accept(Paths.get(info.getId().toString())));
+ }
+
+ @Test
+ public void acceptLocked() throws Exception {
+ UploadInfo info = createExpiredUploadInfo();
+ info.setId(new UploadId(UUID.randomUUID()));
+ info.setOffset(8L);
+ info.setLength(10L);
+ info.updateExpiration(100L);
+
+ when(diskStorageService.getUploadInfo(eq(info.getId()))).thenReturn(info);
+ when(uploadLockingService.isLocked(eq(info.getId()))).thenReturn(true);
+
+ assertFalse(uploadFilter.accept(Paths.get(info.getId().toString())));
+ }
+
+ @Test
+ public void acceptException() throws Exception {
+ UploadInfo info = createExpiredUploadInfo();
+ info.setId(new UploadId(UUID.randomUUID()));
+ info.setOffset(8L);
+ info.setLength(10L);
+ info.updateExpiration(100L);
+
+ when(diskStorageService.getUploadInfo(eq(info.getId()))).thenThrow(new IOException());
+ when(uploadLockingService.isLocked(eq(info.getId()))).thenReturn(false);
+
+ assertFalse(uploadFilter.accept(Paths.get(info.getId().toString())));
+ }
+
+ private UploadInfo createExpiredUploadInfo() throws ParseException {
+ final long time =
+ DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.parse("2018-01-20T10:43:11").getTime();
+
+ return new UploadInfo() {
+ @Override
+ protected long getCurrentTime() {
+ return getExpirationTimestamp() == null ? time : time + 10000L;
+ }
+ };
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/upload/disk/FileBasedLockTest.java b/src/test/java/me/desair/tus/server/upload/disk/FileBasedLockTest.java
index 41058da..be3a757 100644
--- a/src/test/java/me/desair/tus/server/upload/disk/FileBasedLockTest.java
+++ b/src/test/java/me/desair/tus/server/upload/disk/FileBasedLockTest.java
@@ -13,81 +13,82 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
-
import me.desair.tus.server.exception.UploadAlreadyLockedException;
import org.junit.BeforeClass;
import org.junit.Test;
public class FileBasedLockTest {
- private static Path storagePath;
+ private static Path storagePath;
- @BeforeClass
- public static void setupDataFolder() throws IOException {
- storagePath = Paths.get("target", "tus", "locks").toAbsolutePath();
- Files.createDirectories(storagePath);
- }
+ @BeforeClass
+ public static void setupDataFolder() throws IOException {
+ storagePath = Paths.get("target", "tus", "locks").toAbsolutePath();
+ Files.createDirectories(storagePath);
+ }
- @Test
- public void testLockRelease() throws UploadAlreadyLockedException, IOException {
- UUID test = UUID.randomUUID();
- FileBasedLock lock = new FileBasedLock("/test/upload/" + test.toString(), storagePath.resolve(test.toString()));
- lock.release();
- assertFalse(Files.exists(storagePath.resolve(test.toString())));
- }
+ @Test
+ public void testLockRelease() throws UploadAlreadyLockedException, IOException {
+ UUID test = UUID.randomUUID();
+ FileBasedLock lock =
+ new FileBasedLock("/test/upload/" + test.toString(), storagePath.resolve(test.toString()));
+ lock.release();
+ assertFalse(Files.exists(storagePath.resolve(test.toString())));
+ }
- @Test(expected = UploadAlreadyLockedException.class)
- public void testOverlappingLock() throws Exception {
- UUID test = UUID.randomUUID();
- Path path = storagePath.resolve(test.toString());
- try (FileBasedLock lock1 = new FileBasedLock("/test/upload/" + test.toString(), path)) {
- FileBasedLock lock2 = new FileBasedLock("/test/upload/" + test.toString(), path);
- }
+ @Test(expected = UploadAlreadyLockedException.class)
+ public void testOverlappingLock() throws Exception {
+ UUID test = UUID.randomUUID();
+ Path path = storagePath.resolve(test.toString());
+ try (FileBasedLock lock1 = new FileBasedLock("/test/upload/" + test.toString(), path)) {
+ FileBasedLock lock2 = new FileBasedLock("/test/upload/" + test.toString(), path);
}
+ }
- @Test(expected = UploadAlreadyLockedException.class)
- public void testAlreadyLocked() throws Exception {
- UUID test1 = UUID.randomUUID();
- Path path1 = storagePath.resolve(test1.toString());
- try (FileBasedLock lock1 = new FileBasedLock("/test/upload/" + test1.toString(), path1)) {
- FileBasedLock lock2 = new FileBasedLock("/test/upload/" + test1.toString(), path1) {
- @Override
- protected FileChannel createFileChannel() throws IOException {
- FileChannel channel = createFileChannelMock();
- doReturn(null).when(channel).tryLock(anyLong(), anyLong(), anyBoolean());
- return channel;
- }
- };
- }
+ @Test(expected = UploadAlreadyLockedException.class)
+ public void testAlreadyLocked() throws Exception {
+ UUID test1 = UUID.randomUUID();
+ Path path1 = storagePath.resolve(test1.toString());
+ try (FileBasedLock lock1 = new FileBasedLock("/test/upload/" + test1.toString(), path1)) {
+ FileBasedLock lock2 =
+ new FileBasedLock("/test/upload/" + test1.toString(), path1) {
+ @Override
+ protected FileChannel createFileChannel() throws IOException {
+ FileChannel channel = createFileChannelMock();
+ doReturn(null).when(channel).tryLock(anyLong(), anyLong(), anyBoolean());
+ return channel;
+ }
+ };
}
+ }
- @Test
- public void testLockReleaseLockRelease() throws UploadAlreadyLockedException, IOException {
- UUID test = UUID.randomUUID();
- Path path = storagePath.resolve(test.toString());
- FileBasedLock lock = new FileBasedLock("/test/upload/" + test.toString(), path);
- lock.release();
- assertFalse(Files.exists(path));
- lock = new FileBasedLock("/test/upload/" + test.toString(), path);
- lock.release();
- assertFalse(Files.exists(path));
- }
+ @Test
+ public void testLockReleaseLockRelease() throws UploadAlreadyLockedException, IOException {
+ UUID test = UUID.randomUUID();
+ Path path = storagePath.resolve(test.toString());
+ FileBasedLock lock = new FileBasedLock("/test/upload/" + test.toString(), path);
+ lock.release();
+ assertFalse(Files.exists(path));
+ lock = new FileBasedLock("/test/upload/" + test.toString(), path);
+ lock.release();
+ assertFalse(Files.exists(path));
+ }
- @Test(expected = IOException.class)
- public void testLockIOException() throws UploadAlreadyLockedException, IOException {
- //Create directory on place where lock file will be
- UUID test = UUID.randomUUID();
- Path path = storagePath.resolve(test.toString());
- try {
- Files.createDirectories(path);
- } catch (IOException e) {
- fail();
- }
-
- FileBasedLock lock = new FileBasedLock("/test/upload/" + test.toString(), path);
+ @Test(expected = IOException.class)
+ public void testLockIOException() throws UploadAlreadyLockedException, IOException {
+ // Create directory on place where lock file will be
+ UUID test = UUID.randomUUID();
+ Path path = storagePath.resolve(test.toString());
+ try {
+ Files.createDirectories(path);
+ } catch (IOException e) {
+ fail();
}
- private FileChannel createFileChannelMock() throws IOException {
- return spy(FileChannel.class);
- }
-}
\ No newline at end of file
+ FileBasedLock lock = new FileBasedLock("/test/upload/" + test.toString(), path);
+ }
+
+ private FileChannel createFileChannelMock() throws IOException {
+ return spy(FileChannel.class);
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/util/HttpChunkedEncodingInputStreamTest.java b/src/test/java/me/desair/tus/server/util/HttpChunkedEncodingInputStreamTest.java
index 764a677..e8652bb 100644
--- a/src/test/java/me/desair/tus/server/util/HttpChunkedEncodingInputStreamTest.java
+++ b/src/test/java/me/desair/tus/server/util/HttpChunkedEncodingInputStreamTest.java
@@ -11,258 +11,268 @@
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
-
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Test;
public class HttpChunkedEncodingInputStreamTest {
- Map> trailerHeaders;
-
- @Before
- public void setUp() {
- trailerHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ Map> trailerHeaders;
+
+ @Before
+ public void setUp() {
+ trailerHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ }
+
+ @Test
+ public void chunkedWithoutHeaders() throws IOException {
+ String content =
+ "4\r\n"
+ + "Wiki\r\n"
+ + "5\r\n"
+ + "pedia\r\n"
+ + "D\r\n"
+ + " in\n"
+ + "\n\r"
+ + "chunks.\r\n"
+ + "0\r\n"
+ + "\r\n";
+
+ HttpChunkedEncodingInputStream inputStream =
+ new HttpChunkedEncodingInputStream(IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+
+ String expectedContent = "Wikipedia in\n" + "\n\r" + "chunks.";
+
+ StringWriter writer = new StringWriter();
+ IOUtils.copy(inputStream, writer, StandardCharsets.UTF_8);
+ inputStream.close();
+
+ assertEquals(expectedContent, writer.toString());
+ }
+
+ @Test
+ public void chunkedWithHeaders() throws IOException {
+ String content =
+ "8\r\n"
+ + "Mozilla \r\n"
+ + "A\r\n"
+ + "Developer \r\n"
+ + "7\r\n"
+ + "Network\r\n"
+ + "0\r\n"
+ + "Expires: Wed, 21 Oct 2015 07:28:00 GMT\r\n"
+ + "\r\n";
+
+ HttpChunkedEncodingInputStream inputStream =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(content, StandardCharsets.UTF_8), trailerHeaders);
+
+ String expectedContent = "Mozilla Developer Network";
+
+ StringWriter writer = new StringWriter();
+ IOUtils.copy(inputStream, writer, StandardCharsets.UTF_8);
+ inputStream.close();
+
+ assertEquals(expectedContent, writer.toString());
+
+ assertEquals("Wed, 21 Oct 2015 07:28:00 GMT", trailerHeaders.get("expires").get(0));
+ }
+
+ @Test
+ public void chunkedWithFoldedHeaders() throws IOException {
+ String content =
+ "8\r\n"
+ + "Mozilla \r\n"
+ + "A\r\n"
+ + "Developer \r\n"
+ + "7\r\n"
+ + "Network\r\n"
+ + "0\r\n"
+ + "Expires: Wed, 21 Oct 2015\n"
+ + " 07:28:00 GMT\r\n"
+ + "Cookie: ABC\n"
+ + "\tDEF\r\n"
+ + "\r\n";
+
+ HttpChunkedEncodingInputStream inputStream =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(content, StandardCharsets.UTF_8), trailerHeaders);
+
+ String expectedContent = "Mozilla Developer Network";
+
+ StringWriter writer = new StringWriter();
+ IOUtils.copy(inputStream, writer, StandardCharsets.UTF_8);
+ inputStream.close();
+
+ assertEquals(expectedContent, writer.toString());
+
+ assertEquals("Wed, 21 Oct 2015 07:28:00 GMT", trailerHeaders.get("expires").get(0));
+ assertEquals("ABC DEF", trailerHeaders.get("cookie").get(0));
+ }
+
+ @Test
+ public void testChunkedInputStream() throws IOException {
+ String correctInput =
+ "10;key=\"value\r\n"
+ + "newline\"\r\n"
+ + "1234567890"
+ + "123456\r\n"
+ + "5\r\n"
+ + "12345\r\n"
+ + "0\r\n"
+ + "Footer1: abcde\r\n"
+ + "Footer2: fghij\r\n";
+
+ String correctResult = "123456789012345612345";
+
+ // Test for when buffer is larger than chunk size
+ InputStream in =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(correctInput, StandardCharsets.UTF_8), trailerHeaders);
+ StringWriter writer = new StringWriter();
+ IOUtils.copy(in, writer, StandardCharsets.UTF_8);
+ in.close();
+
+ assertEquals(correctResult, writer.toString());
+
+ assertEquals("abcde", trailerHeaders.get("footer1").get(0));
+ assertEquals("fghij", trailerHeaders.get("footer2").get(0));
+ }
+
+ @Test(expected = IOException.class)
+ public void testCorruptChunkedInputStream1() throws IOException {
+ // missing \r\n at the end of the first chunk
+ String corruptInput =
+ "10;key=\"val\\ue\"\r\n"
+ + "1234567890"
+ + "12345\r\n"
+ + "5\r\n"
+ + "12345\r\n"
+ + "0\r\n"
+ + "Footer1: abcde\r\n"
+ + "Footer2: fghij\r\n";
+
+ InputStream in =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(corruptInput, StandardCharsets.UTF_8), trailerHeaders);
+ StringWriter writer = new StringWriter();
+ IOUtils.copy(in, writer, StandardCharsets.UTF_8);
+ }
+
+ @Test
+ public void testEmptyChunkedInputStream() throws IOException {
+ String input = "0\r\n";
+ InputStream in =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(input, StandardCharsets.UTF_8), trailerHeaders);
+ StringWriter writer = new StringWriter();
+ IOUtils.copy(in, writer, StandardCharsets.UTF_8);
+ assertEquals(0, writer.toString().length());
+ }
+
+ @Test
+ public void testReadPartialByteArray() throws IOException {
+ String input = "A\r\n0123456789\r\n0\r\n";
+ InputStream in =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(input, StandardCharsets.UTF_8), trailerHeaders);
+
+ byte[] byteArray = new byte[5];
+ in.read(byteArray);
+ in.close();
+
+ assertEquals("01234", new String(byteArray));
+ }
+
+ @Test
+ public void testReadByte() throws IOException {
+ String input = "4\r\n" + "0123\r\n" + "6\r\n" + "456789\r\n0\r\n";
+ InputStream in =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(input, StandardCharsets.UTF_8), trailerHeaders);
+
+ assertEquals('0', (char) in.read());
+ assertEquals('1', (char) in.read());
+ assertEquals('2', (char) in.read());
+ assertEquals('3', (char) in.read());
+ assertEquals('4', (char) in.read());
+ assertEquals('5', (char) in.read());
+ assertEquals('6', (char) in.read());
+ assertEquals('7', (char) in.read());
+ assertEquals('8', (char) in.read());
+ assertEquals('9', (char) in.read());
+ in.close();
+ }
+
+ @Test
+ public void testReadEof() throws IOException {
+ String input = "A\r\n0123456789\r\n0\r\n";
+ InputStream in =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(input, StandardCharsets.UTF_8), trailerHeaders);
+
+ byte[] byteArray = new byte[10];
+ in.read(byteArray);
+
+ assertEquals(-1, in.read());
+ assertEquals(-1, in.read());
+ }
+
+ @Test
+ public void testReadEof2() throws IOException {
+ String input = "A\r\n0123456789\r\n0\r\n";
+ InputStream in =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(input, StandardCharsets.UTF_8), trailerHeaders);
+
+ byte[] byteArray = new byte[10];
+ in.read(byteArray);
+
+ assertEquals(-1, in.read(byteArray));
+ assertEquals(-1, in.read(byteArray));
+ }
+
+ @Test
+ public void testReadClosed() throws IOException {
+ String input = "A\r\n0123456789\r\n0\r\n";
+ InputStream in =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(input, StandardCharsets.UTF_8), trailerHeaders);
+
+ in.close();
+
+ try {
+ byte[] byteArray = new byte[10];
+ assertEquals(-1, in.read(byteArray));
+ fail();
+ } catch (Exception ex) {
+ assertTrue(ex instanceof IOException);
}
- @Test
- public void chunkedWithoutHeaders() throws IOException {
- String content = "4\r\n" +
- "Wiki\r\n" +
- "5\r\n" +
- "pedia\r\n" +
- "D\r\n" +
- " in\n" +
- "\n\r" +
- "chunks.\r\n" +
- "0\r\n" +
- "\r\n";
-
- HttpChunkedEncodingInputStream inputStream = new HttpChunkedEncodingInputStream(
- IOUtils.toInputStream(content, StandardCharsets.UTF_8));
-
- String expectedContent = "Wikipedia in\n" +
- "\n\r" +
- "chunks.";
-
- StringWriter writer = new StringWriter();
- IOUtils.copy(inputStream, writer, StandardCharsets.UTF_8);
- inputStream.close();
-
- assertEquals(expectedContent, writer.toString());
- }
-
- @Test
- public void chunkedWithHeaders() throws IOException {
- String content = "8\r\n" +
- "Mozilla \r\n" +
- "A\r\n" +
- "Developer \r\n" +
- "7\r\n" +
- "Network\r\n" +
- "0\r\n" +
- "Expires: Wed, 21 Oct 2015 07:28:00 GMT\r\n" +
- "\r\n";
-
- HttpChunkedEncodingInputStream inputStream = new HttpChunkedEncodingInputStream(
- IOUtils.toInputStream(content, StandardCharsets.UTF_8), trailerHeaders);
-
- String expectedContent = "Mozilla Developer Network";
-
- StringWriter writer = new StringWriter();
- IOUtils.copy(inputStream, writer, StandardCharsets.UTF_8);
- inputStream.close();
-
- assertEquals(expectedContent, writer.toString());
-
- assertEquals("Wed, 21 Oct 2015 07:28:00 GMT", trailerHeaders.get("expires").get(0));
+ try {
+ assertEquals(-1, in.read());
+ fail();
+ } catch (Exception ex) {
+ assertTrue(ex instanceof IOException);
}
- @Test
- public void chunkedWithFoldedHeaders() throws IOException {
- String content = "8\r\n" +
- "Mozilla \r\n" +
- "A\r\n" +
- "Developer \r\n" +
- "7\r\n" +
- "Network\r\n" +
- "0\r\n" +
- "Expires: Wed, 21 Oct 2015\n" +
- " 07:28:00 GMT\r\n" +
- "Cookie: ABC\n" +
- "\tDEF\r\n" +
- "\r\n";
-
- HttpChunkedEncodingInputStream inputStream = new HttpChunkedEncodingInputStream(
- IOUtils.toInputStream(content, StandardCharsets.UTF_8), trailerHeaders);
-
- String expectedContent = "Mozilla Developer Network";
-
- StringWriter writer = new StringWriter();
- IOUtils.copy(inputStream, writer, StandardCharsets.UTF_8);
- inputStream.close();
-
- assertEquals(expectedContent, writer.toString());
-
- assertEquals("Wed, 21 Oct 2015 07:28:00 GMT", trailerHeaders.get("expires").get(0));
- assertEquals("ABC DEF", trailerHeaders.get("cookie").get(0));
- }
-
- @Test
- public void testChunkedInputStream() throws IOException {
- String correctInput = "10;key=\"value\r\n" +
- "newline\"\r\n" +
- "1234567890" +
- "123456\r\n" +
- "5\r\n" +
- "12345\r\n" +
- "0\r\n" +
- "Footer1: abcde\r\n" +
- "Footer2: fghij\r\n";
-
- String correctResult = "123456789012345612345";
-
- //Test for when buffer is larger than chunk size
- InputStream in = new HttpChunkedEncodingInputStream(IOUtils.toInputStream(correctInput, StandardCharsets.UTF_8),
- trailerHeaders);
- StringWriter writer = new StringWriter();
- IOUtils.copy(in, writer, StandardCharsets.UTF_8);
- in.close();
-
- assertEquals(correctResult, writer.toString());
-
- assertEquals("abcde", trailerHeaders.get("footer1").get(0));
- assertEquals("fghij", trailerHeaders.get("footer2").get(0));
- }
-
- @Test(expected = IOException.class)
- public void testCorruptChunkedInputStream1() throws IOException {
- //missing \r\n at the end of the first chunk
- String corruptInput = "10;key=\"val\\ue\"\r\n" +
- "1234567890" +
- "12345\r\n" +
- "5\r\n" +
- "12345\r\n" +
- "0\r\n" +
- "Footer1: abcde\r\n" +
- "Footer2: fghij\r\n";
-
- InputStream in = new HttpChunkedEncodingInputStream(IOUtils.toInputStream(corruptInput, StandardCharsets.UTF_8),
- trailerHeaders);
- StringWriter writer = new StringWriter();
- IOUtils.copy(in, writer, StandardCharsets.UTF_8);
- }
-
- @Test
- public void testEmptyChunkedInputStream() throws IOException {
- String input = "0\r\n";
- InputStream in = new HttpChunkedEncodingInputStream(IOUtils.toInputStream(input, StandardCharsets.UTF_8),
- trailerHeaders);
- StringWriter writer = new StringWriter();
- IOUtils.copy(in, writer, StandardCharsets.UTF_8);
- assertEquals(0, writer.toString().length());
- }
-
- @Test
- public void testReadPartialByteArray() throws IOException {
- String input = "A\r\n0123456789\r\n0\r\n";
- InputStream in = new HttpChunkedEncodingInputStream(IOUtils.toInputStream(input, StandardCharsets.UTF_8),
- trailerHeaders);
-
- byte[] byteArray = new byte[5];
- in.read(byteArray);
- in.close();
-
- assertEquals("01234", new String(byteArray));
- }
-
- @Test
- public void testReadByte() throws IOException {
- String input = "4\r\n" +
- "0123\r\n" +
- "6\r\n" +
- "456789\r\n0\r\n";
- InputStream in = new HttpChunkedEncodingInputStream(IOUtils.toInputStream(input, StandardCharsets.UTF_8),
- trailerHeaders);
-
- assertEquals('0', (char) in.read());
- assertEquals('1', (char) in.read());
- assertEquals('2', (char) in.read());
- assertEquals('3', (char) in.read());
- assertEquals('4', (char) in.read());
- assertEquals('5', (char) in.read());
- assertEquals('6', (char) in.read());
- assertEquals('7', (char) in.read());
- assertEquals('8', (char) in.read());
- assertEquals('9', (char) in.read());
- in.close();
- }
-
- @Test
- public void testReadEof() throws IOException {
- String input = "A\r\n0123456789\r\n0\r\n";
- InputStream in = new HttpChunkedEncodingInputStream(IOUtils.toInputStream(input, StandardCharsets.UTF_8),
- trailerHeaders);
-
- byte[] byteArray = new byte[10];
- in.read(byteArray);
-
- assertEquals(-1, in.read());
- assertEquals(-1, in.read());
- }
-
- @Test
- public void testReadEof2() throws IOException {
- String input = "A\r\n0123456789\r\n0\r\n";
- InputStream in = new HttpChunkedEncodingInputStream(IOUtils.toInputStream(input, StandardCharsets.UTF_8),
- trailerHeaders);
-
- byte[] byteArray = new byte[10];
- in.read(byteArray);
-
- assertEquals(-1, in.read(byteArray));
- assertEquals(-1, in.read(byteArray));
- }
-
- @Test
- public void testReadClosed() throws IOException {
- String input = "A\r\n0123456789\r\n0\r\n";
- InputStream in = new HttpChunkedEncodingInputStream(IOUtils.toInputStream(input, StandardCharsets.UTF_8),
- trailerHeaders);
-
- in.close();
-
- try {
- byte[] byteArray = new byte[10];
- assertEquals(-1, in.read(byteArray));
- fail();
- } catch (Exception ex) {
- assertTrue(ex instanceof IOException);
- }
-
- try {
- assertEquals(-1, in.read());
- fail();
- } catch (Exception ex) {
- assertTrue(ex instanceof IOException);
- }
-
- //double close has not effect
- in.close();
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testNullInputstream() throws IOException {
- InputStream in = new HttpChunkedEncodingInputStream(null);
- }
-
- @Test(expected = IOException.class)
- public void testNegativeChunkSize() throws IOException {
- String input = "-A\r\n0123456789\r\n0\r\n";
- InputStream in = new HttpChunkedEncodingInputStream(IOUtils.toInputStream(input, StandardCharsets.UTF_8),
- trailerHeaders);
-
- byte[] byteArray = new byte[10];
- in.read(byteArray);
- }
-}
\ No newline at end of file
+ // double close has not effect
+ in.close();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullInputstream() throws IOException {
+ InputStream in = new HttpChunkedEncodingInputStream(null);
+ }
+
+ @Test(expected = IOException.class)
+ public void testNegativeChunkSize() throws IOException {
+ String input = "-A\r\n0123456789\r\n0\r\n";
+ InputStream in =
+ new HttpChunkedEncodingInputStream(
+ IOUtils.toInputStream(input, StandardCharsets.UTF_8), trailerHeaders);
+
+ byte[] byteArray = new byte[10];
+ in.read(byteArray);
+ }
+}
diff --git a/src/test/java/me/desair/tus/server/util/MapMatcher.java b/src/test/java/me/desair/tus/server/util/MapMatcher.java
index bc58fb5..47dd44d 100644
--- a/src/test/java/me/desair/tus/server/util/MapMatcher.java
+++ b/src/test/java/me/desair/tus/server/util/MapMatcher.java
@@ -1,31 +1,26 @@
package me.desair.tus.server.util;
import java.util.Map;
-
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
-/**
- * Custom Matcher class used in tests
- */
+/** Custom Matcher class used in tests */
public class MapMatcher {
- private MapMatcher() {
- }
-
- public static Matcher