package org.dcache.webdav; import io.milton.http.Filter; import io.milton.http.FilterChain; import io.milton.http.Handler; import io.milton.http.HttpManager; import io.milton.http.Request; import io.milton.http.Response; import io.milton.http.exceptions.BadRequestException; import io.milton.http.exceptions.ConflictException; import io.milton.http.exceptions.NotAuthorizedException; import io.milton.http.exceptions.NotFoundException; import io.milton.http.http11.Http11ResponseHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Custom StandardFilter for Milton. * * As we do some things differently in dCache than expected by the * Milton WebDAV framework, we cannot always perform error handling * the Milton way. We therefore have a hierarchy of WebDAV * RuntimeExceptions which are caught by DcacheStandardFilter and * translated to HTTP response codes. * * Essentially the same as com.bradmcevoy.http.StandardFilter. */ public class DcacheStandardFilter implements Filter { private static final Logger log = LoggerFactory.getLogger(DcacheStandardFilter.class); @Override public void process(FilterChain chain, Request request, Response response) { HttpManager manager = chain.getHttpManager(); Http11ResponseHandler responseHandler = manager.getResponseHandler(); try { Request.Method method = request.getMethod(); Handler handler = manager.getMethodHandler(method); if (handler == null) { responseHandler.respondMethodNotImplemented(new EmptyResource(request), response, request); return; } try { handler.process(manager,request,response); if (response.getEntity() != null) { manager.sendResponseEntity(response); } } catch (RuntimeException e) { /* Milton wraps our WebDavException in a * RuntimeException. */ if (e.getCause() instanceof WebDavException) { throw (WebDavException) e.getCause(); } /* Milton also wraps critical errors that should not * be caught. */ if (e.getCause() instanceof Error) { throw (Error) e.getCause(); } throw e; } } catch (BadRequestException e) { responseHandler.respondBadRequest(e.getResource(), response, request); } catch (ConflictException e) { responseHandler.respondConflict(e.getResource(), response, request, e.getMessage()); } catch (NotAuthorizedException e) { responseHandler.respondUnauthorised(e.getResource(), response, request); } catch (UnauthorizedException e) { responseHandler.respondUnauthorised(e.getResource(), response, request); } catch (ForbiddenException e) { responseHandler.respondForbidden(e.getResource(), response, request); } catch (NotFoundException e) { responseHandler.respondNotFound(response, request); } catch (RedirectException e) { /* Milton's response handler does not support selecting the type of * redirect to use, so we need this workaround to issue a 307 reply. * * See http://jira.ettrema.com:8080/browse/MIL-120 */ response.setStatus(Response.Status.SC_TEMPORARY_REDIRECT); response.setLocationHeader(e.getUrl()); } catch (WebDavException e) { log.warn("Internal server error: {}", e.toString()); responseHandler.respondServerError(request, response, e.getMessage()); } catch (RuntimeException e) { log.error("Internal server error", e); responseHandler.respondServerError(request, response, e.getMessage()); } catch (Exception e) { log.error("Internal server error: {}", e.toString()); responseHandler.respondServerError(request, response, e.getMessage()); } finally { manager.closeResponse(response); } } }