|
@@ -36,6 +36,7 @@ import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.GroupParam;
|
|
|
import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.LenParam;
|
|
|
import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.ModifiedTimeParam;
|
|
|
import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.NewLengthParam;
|
|
|
+import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.NoRedirectParam;
|
|
|
import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.OffsetParam;
|
|
|
import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.OldSnapshotNameParam;
|
|
|
import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.OperationParam;
|
|
@@ -52,6 +53,7 @@ import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.XAttrEncodingPa
|
|
|
import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.XAttrNameParam;
|
|
|
import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.XAttrSetFlagParam;
|
|
|
import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.XAttrValueParam;
|
|
|
+import org.apache.hadoop.hdfs.web.JsonUtil;
|
|
|
import org.apache.hadoop.http.JettyUtils;
|
|
|
import org.apache.hadoop.lib.service.FileSystemAccess;
|
|
|
import org.apache.hadoop.lib.service.FileSystemAccessException;
|
|
@@ -161,6 +163,7 @@ public class HttpFSServer {
|
|
|
/**
|
|
|
* Special binding for '/' as it is not handled by the wildcard binding.
|
|
|
*
|
|
|
+ * @param uriInfo uri info of the request.
|
|
|
* @param op the HttpFS operation of the request.
|
|
|
* @param params the HttpFS parameters of the request.
|
|
|
*
|
|
@@ -174,11 +177,12 @@ public class HttpFSServer {
|
|
|
*/
|
|
|
@GET
|
|
|
@Produces(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8)
|
|
|
- public Response getRoot(@QueryParam(OperationParam.NAME) OperationParam op,
|
|
|
+ public Response getRoot(@Context UriInfo uriInfo,
|
|
|
+ @QueryParam(OperationParam.NAME) OperationParam op,
|
|
|
@Context Parameters params,
|
|
|
@Context HttpServletRequest request)
|
|
|
throws IOException, FileSystemAccessException {
|
|
|
- return get("", op, params, request);
|
|
|
+ return get("", uriInfo, op, params, request);
|
|
|
}
|
|
|
|
|
|
private String makeAbsolute(String path) {
|
|
@@ -189,6 +193,7 @@ public class HttpFSServer {
|
|
|
* Binding to handle GET requests, supported operations are
|
|
|
*
|
|
|
* @param path the path for operation.
|
|
|
+ * @param uriInfo uri info of the request.
|
|
|
* @param op the HttpFS operation of the request.
|
|
|
* @param params the HttpFS parameters of the request.
|
|
|
*
|
|
@@ -205,6 +210,7 @@ public class HttpFSServer {
|
|
|
@Produces({MediaType.APPLICATION_OCTET_STREAM + "; " + JettyUtils.UTF_8,
|
|
|
MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8})
|
|
|
public Response get(@PathParam("path") String path,
|
|
|
+ @Context UriInfo uriInfo,
|
|
|
@QueryParam(OperationParam.NAME) OperationParam op,
|
|
|
@Context Parameters params,
|
|
|
@Context HttpServletRequest request)
|
|
@@ -216,32 +222,40 @@ public class HttpFSServer {
|
|
|
MDC.put("hostname", request.getRemoteAddr());
|
|
|
switch (op.value()) {
|
|
|
case OPEN: {
|
|
|
- //Invoking the command directly using an unmanaged FileSystem that is
|
|
|
- // released by the FileSystemReleaseFilter
|
|
|
- final FSOperations.FSOpen command = new FSOperations.FSOpen(path);
|
|
|
- final FileSystem fs = createFileSystem(user);
|
|
|
- InputStream is = null;
|
|
|
- UserGroupInformation ugi = UserGroupInformation
|
|
|
- .createProxyUser(user.getShortUserName(),
|
|
|
- UserGroupInformation.getLoginUser());
|
|
|
- try {
|
|
|
- is = ugi.doAs(new PrivilegedExceptionAction<InputStream>() {
|
|
|
- @Override
|
|
|
- public InputStream run() throws Exception {
|
|
|
- return command.execute(fs);
|
|
|
- }
|
|
|
- });
|
|
|
- } catch (InterruptedException ie) {
|
|
|
- LOG.info("Open interrupted.", ie);
|
|
|
- Thread.currentThread().interrupt();
|
|
|
- }
|
|
|
- Long offset = params.get(OffsetParam.NAME, OffsetParam.class);
|
|
|
- Long len = params.get(LenParam.NAME, LenParam.class);
|
|
|
- AUDIT_LOG.info("[{}] offset [{}] len [{}]",
|
|
|
- new Object[] { path, offset, len });
|
|
|
- InputStreamEntity entity = new InputStreamEntity(is, offset, len);
|
|
|
- response =
|
|
|
- Response.ok(entity).type(MediaType.APPLICATION_OCTET_STREAM).build();
|
|
|
+ Boolean noRedirect = params.get(
|
|
|
+ NoRedirectParam.NAME, NoRedirectParam.class);
|
|
|
+ if (noRedirect) {
|
|
|
+ URI redirectURL = createOpenRedirectionURL(uriInfo);
|
|
|
+ final String js = JsonUtil.toJsonString("Location", redirectURL);
|
|
|
+ response = Response.ok(js).type(MediaType.APPLICATION_JSON).build();
|
|
|
+ } else {
|
|
|
+ //Invoking the command directly using an unmanaged FileSystem that is
|
|
|
+ // released by the FileSystemReleaseFilter
|
|
|
+ final FSOperations.FSOpen command = new FSOperations.FSOpen(path);
|
|
|
+ final FileSystem fs = createFileSystem(user);
|
|
|
+ InputStream is = null;
|
|
|
+ UserGroupInformation ugi = UserGroupInformation
|
|
|
+ .createProxyUser(user.getShortUserName(),
|
|
|
+ UserGroupInformation.getLoginUser());
|
|
|
+ try {
|
|
|
+ is = ugi.doAs(new PrivilegedExceptionAction<InputStream>() {
|
|
|
+ @Override
|
|
|
+ public InputStream run() throws Exception {
|
|
|
+ return command.execute(fs);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } catch (InterruptedException ie) {
|
|
|
+ LOG.info("Open interrupted.", ie);
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ }
|
|
|
+ Long offset = params.get(OffsetParam.NAME, OffsetParam.class);
|
|
|
+ Long len = params.get(LenParam.NAME, LenParam.class);
|
|
|
+ AUDIT_LOG.info("[{}] offset [{}] len [{}]",
|
|
|
+ new Object[] { path, offset, len });
|
|
|
+ InputStreamEntity entity = new InputStreamEntity(is, offset, len);
|
|
|
+ response = Response.ok(entity).type(MediaType.APPLICATION_OCTET_STREAM)
|
|
|
+ .build();
|
|
|
+ }
|
|
|
break;
|
|
|
}
|
|
|
case GETFILESTATUS: {
|
|
@@ -293,9 +307,18 @@ public class HttpFSServer {
|
|
|
case GETFILECHECKSUM: {
|
|
|
FSOperations.FSFileChecksum command =
|
|
|
new FSOperations.FSFileChecksum(path);
|
|
|
- Map json = fsExecute(user, command);
|
|
|
+
|
|
|
+ Boolean noRedirect = params.get(
|
|
|
+ NoRedirectParam.NAME, NoRedirectParam.class);
|
|
|
AUDIT_LOG.info("[{}]", path);
|
|
|
- response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
|
|
|
+ if (noRedirect) {
|
|
|
+ URI redirectURL = createOpenRedirectionURL(uriInfo);
|
|
|
+ final String js = JsonUtil.toJsonString("Location", redirectURL);
|
|
|
+ response = Response.ok(js).type(MediaType.APPLICATION_JSON).build();
|
|
|
+ } else {
|
|
|
+ Map json = fsExecute(user, command);
|
|
|
+ response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
|
|
|
+ }
|
|
|
break;
|
|
|
}
|
|
|
case GETFILEBLOCKLOCATIONS: {
|
|
@@ -395,6 +418,17 @@ public class HttpFSServer {
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Create an open redirection URL from a request. It points to the same
|
|
|
+ * HttpFS endpoint but removes the "redirect" parameter.
|
|
|
+ * @param uriInfo uri info of the request.
|
|
|
+ * @return URL for the redirected location.
|
|
|
+ */
|
|
|
+ private URI createOpenRedirectionURL(UriInfo uriInfo) {
|
|
|
+ UriBuilder uriBuilder = uriInfo.getRequestUriBuilder();
|
|
|
+ uriBuilder.replaceQueryParam(NoRedirectParam.NAME, (Object[])null);
|
|
|
+ return uriBuilder.build((Object[])null);
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* Binding to handle DELETE requests.
|
|
@@ -491,9 +525,16 @@ public class HttpFSServer {
|
|
|
case APPEND: {
|
|
|
Boolean hasData = params.get(DataParam.NAME, DataParam.class);
|
|
|
if (!hasData) {
|
|
|
- response = Response.temporaryRedirect(
|
|
|
- createUploadRedirectionURL(uriInfo,
|
|
|
- HttpFSFileSystem.Operation.APPEND)).build();
|
|
|
+ URI redirectURL = createUploadRedirectionURL(
|
|
|
+ uriInfo, HttpFSFileSystem.Operation.APPEND);
|
|
|
+ Boolean noRedirect = params.get(
|
|
|
+ NoRedirectParam.NAME, NoRedirectParam.class);
|
|
|
+ if (noRedirect) {
|
|
|
+ final String js = JsonUtil.toJsonString("Location", redirectURL);
|
|
|
+ response = Response.ok(js).type(MediaType.APPLICATION_JSON).build();
|
|
|
+ } else {
|
|
|
+ response = Response.temporaryRedirect(redirectURL).build();
|
|
|
+ }
|
|
|
} else {
|
|
|
FSOperations.FSAppend command =
|
|
|
new FSOperations.FSAppend(is, path);
|
|
@@ -594,9 +635,16 @@ public class HttpFSServer {
|
|
|
case CREATE: {
|
|
|
Boolean hasData = params.get(DataParam.NAME, DataParam.class);
|
|
|
if (!hasData) {
|
|
|
- response = Response.temporaryRedirect(
|
|
|
- createUploadRedirectionURL(uriInfo,
|
|
|
- HttpFSFileSystem.Operation.CREATE)).build();
|
|
|
+ URI redirectURL = createUploadRedirectionURL(
|
|
|
+ uriInfo, HttpFSFileSystem.Operation.CREATE);
|
|
|
+ Boolean noRedirect = params.get(
|
|
|
+ NoRedirectParam.NAME, NoRedirectParam.class);
|
|
|
+ if (noRedirect) {
|
|
|
+ final String js = JsonUtil.toJsonString("Location", redirectURL);
|
|
|
+ response = Response.ok(js).type(MediaType.APPLICATION_JSON).build();
|
|
|
+ } else {
|
|
|
+ response = Response.temporaryRedirect(redirectURL).build();
|
|
|
+ }
|
|
|
} else {
|
|
|
Short permission = params.get(PermissionParam.NAME,
|
|
|
PermissionParam.class);
|
|
@@ -617,7 +665,10 @@ public class HttpFSServer {
|
|
|
"replication [{}] blockSize [{}] unmaskedpermission [{}]",
|
|
|
new Object[]{path, permission, override, replication, blockSize,
|
|
|
unmaskedPermission});
|
|
|
- response = Response.status(Response.Status.CREATED).build();
|
|
|
+ final String js = JsonUtil.toJsonString(
|
|
|
+ "Location", uriInfo.getAbsolutePath());
|
|
|
+ response = Response.created(uriInfo.getAbsolutePath())
|
|
|
+ .type(MediaType.APPLICATION_JSON).entity(js).build();
|
|
|
}
|
|
|
break;
|
|
|
}
|