001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.fs.http.server; 020 021 022import org.apache.hadoop.classification.InterfaceAudience; 023import org.apache.hadoop.fs.http.client.HttpFSFileSystem; 024import org.apache.hadoop.util.StringUtils; 025 026import javax.servlet.Filter; 027import javax.servlet.FilterChain; 028import javax.servlet.FilterConfig; 029import javax.servlet.ServletException; 030import javax.servlet.ServletRequest; 031import javax.servlet.ServletResponse; 032import javax.servlet.http.HttpServletRequest; 033import javax.servlet.http.HttpServletResponse; 034import java.io.IOException; 035import java.util.HashSet; 036import java.util.Set; 037 038/** 039 * Filter that Enforces the content-type to be application/octet-stream for 040 * POST and PUT requests. 041 */ 042@InterfaceAudience.Private 043public class CheckUploadContentTypeFilter implements Filter { 044 045 private static final Set<String> UPLOAD_OPERATIONS = new HashSet<String>(); 046 047 static { 048 UPLOAD_OPERATIONS.add(HttpFSFileSystem.Operation.APPEND.toString()); 049 UPLOAD_OPERATIONS.add(HttpFSFileSystem.Operation.CREATE.toString()); 050 } 051 052 /** 053 * Initializes the filter. 054 * <p> 055 * This implementation is a NOP. 056 * 057 * @param config filter configuration. 058 * 059 * @throws ServletException thrown if the filter could not be initialized. 060 */ 061 @Override 062 public void init(FilterConfig config) throws ServletException { 063 } 064 065 /** 066 * Enforces the content-type to be application/octet-stream for 067 * POST and PUT requests. 068 * 069 * @param request servlet request. 070 * @param response servlet response. 071 * @param chain filter chain. 072 * 073 * @throws IOException thrown if an IO error occurrs. 074 * @throws ServletException thrown if a servet error occurrs. 075 */ 076 @Override 077 public void doFilter(ServletRequest request, ServletResponse response, 078 FilterChain chain) 079 throws IOException, ServletException { 080 boolean contentTypeOK = true; 081 HttpServletRequest httpReq = (HttpServletRequest) request; 082 HttpServletResponse httpRes = (HttpServletResponse) response; 083 String method = httpReq.getMethod(); 084 if (method.equals("PUT") || method.equals("POST")) { 085 String op = httpReq.getParameter(HttpFSFileSystem.OP_PARAM); 086 if (op != null && UPLOAD_OPERATIONS.contains( 087 StringUtils.toUpperCase(op))) { 088 if ("true".equalsIgnoreCase(httpReq.getParameter(HttpFSParametersProvider.DataParam.NAME))) { 089 String contentType = httpReq.getContentType(); 090 contentTypeOK = 091 HttpFSFileSystem.UPLOAD_CONTENT_TYPE.equalsIgnoreCase(contentType); 092 } 093 } 094 } 095 if (contentTypeOK) { 096 chain.doFilter(httpReq, httpRes); 097 } 098 else { 099 httpRes.sendError(HttpServletResponse.SC_BAD_REQUEST, 100 "Data upload requests must have content-type set to '" + 101 HttpFSFileSystem.UPLOAD_CONTENT_TYPE + "'"); 102 103 } 104 } 105 106 /** 107 * Destroys the filter. 108 * <p> 109 * This implementation is a NOP. 110 */ 111 @Override 112 public void destroy() { 113 } 114 115}