package net.dev123.commons.http; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import net.dev123.commons.ServiceProvider; import net.dev123.commons.http.auth.Authorization; import net.dev123.commons.http.auth.BasicAuthorization; import net.dev123.commons.http.auth.OAuth2Authorization; import net.dev123.commons.http.auth.OAuthAccessorFactory; import net.dev123.commons.http.auth.OAuthAuthorization; import net.dev123.commons.oauth.OAuthAccessor; import net.dev123.commons.oauth.OAuthException; import net.dev123.commons.oauth2.OAuth2; import net.dev123.commons.util.Base64; import net.dev123.commons.util.FileUtil; import net.dev123.commons.util.MimeTypeUtil; import net.dev123.commons.util.StringUtil; import net.dev123.commons.util.UrlUtil; import net.dev123.exception.LibException; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpRequest; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.message.BasicNameValuePair; public class HttpRequestBuilder { public static HttpRequest newHttpRequest(HttpRequestMessage httpRequestMessage) throws OAuthException, IOException, URISyntaxException, LibException { URI uri = URI.create(httpRequestMessage.getUrl()); boolean hasQuery = false; if (StringUtil.isNotEmpty(uri.getQuery())){ hasQuery = true; //提取Query中的参数,添加到参数列表 Map<String, String> queryParameters = UrlUtil.extractQueryStringParameters(uri); httpRequestMessage.addParameters(queryParameters); } String requestUrl = uri.toASCIIString(); //此方法将所有URL中的非ASCII码字符使用UTF-8进行编码 if (hasQuery){ // Query中的参数已提取出来,去除url中的Query requestUrl = requestUrl.substring(0, requestUrl.indexOf("?")); } httpRequestMessage.setUrl(requestUrl); Map<String, File> fileParameters = new HashMap<String, File>(); Iterator<Map.Entry<String, Object>> iterator = httpRequestMessage.getParameters().entrySet().iterator(); while (iterator.hasNext()) { // 遍历参数,提取出文件参数,文件参数通常需要特殊处理,比如不参与OAuth签名 Map.Entry<String, Object> entry = iterator.next(); if (entry.getValue() instanceof File) { final String encodedName = URLEncoder.encode(entry.getKey(), "UTF-8"); fileParameters.put(encodedName, (File) entry.getValue()); iterator.remove(); } } Authorization auth = httpRequestMessage.getAuth(); if (auth instanceof OAuthAuthorization) { if (ServiceProvider.Fanfou == auth.getServiceProvider() || ServiceProvider.Twitter == auth.getServiceProvider()) { boolean isMultipartRequest = fileParameters.size() > 0; Map<String, Object> stringParameters = null; if (isMultipartRequest) { stringParameters = new HashMap<String, Object>(httpRequestMessage.getParameters()); httpRequestMessage.clearParameters(); // 饭否文件上传时所有参数都不参与签名 } // 对OAuth请求进行签名,签名方法会根据OAuth参数风格进行请求URL的OAuth参数添加或者认证头部的添加 OAuthAccessor accessor = OAuthAccessorFactory.getOAuthAccessorInstance((OAuthAuthorization) auth); accessor.sign(httpRequestMessage); if (isMultipartRequest) { //把之前清除的参数再给重新置回去,以便进行下一步操作 httpRequestMessage.addParameters(stringParameters); } } else { // 对OAuth请求进行签名,签名方法会根据OAuth参数风格进行请求URL的OAuth参数添加或者认证头部的添加 OAuthAccessor accessor = OAuthAccessorFactory.getOAuthAccessorInstance((OAuthAuthorization) auth); accessor.sign(httpRequestMessage); } } else if (auth instanceof OAuth2Authorization) { httpRequestMessage.addParameter(OAuth2.ACCESS_TOKEN, auth.getAuthToken()); } else if (auth instanceof BasicAuthorization) { // Basic认证头部添加 httpRequestMessage.addHeader("Authorization", getBasicAuthorizationHeader((BasicAuthorization) auth)); } HttpRequest httpRequest = buildHttpRequest(httpRequestMessage, fileParameters); return httpRequest; } private static HttpRequest buildHttpRequest(HttpRequestMessage httpRequestMessage, Map<String, File> fileParameters) throws IOException, UnsupportedEncodingException { HttpRequest httpRequest = null; String requestUrl = httpRequestMessage.getUrl(); HttpMethod method = httpRequestMessage.getMethod(); switch (method) { case GET: case DELETE: if (httpRequestMessage.getParameters().size() > 0) { requestUrl = UrlUtil.appendQueryParameters(requestUrl, httpRequestMessage.getParameters(), "UTF-8"); } if (method == HttpMethod.GET) { httpRequest = new HttpGet(requestUrl); } else { httpRequest = new HttpDelete(requestUrl); } break; case POST: case PUT: HttpEntityEnclosingRequest httpEntityEnclosingRequest = null; if (method == HttpMethod.POST) { httpEntityEnclosingRequest = new HttpPost(requestUrl); } else { httpEntityEnclosingRequest = new HttpPut(requestUrl); } if (fileParameters.size() > 0) { MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.STRICT); for (Map.Entry<String, Object> entry : httpRequestMessage.getParameters().entrySet()) { StringBody strBody = new StringBody(String.valueOf(entry.getValue()), Charset.forName("UTF-8")); multipartEntity.addPart(entry.getKey(), strBody); } File file = null; String fileExtension = null; String mineType = null; for (Map.Entry<String, File> entry : fileParameters.entrySet()) { file = entry.getValue(); fileExtension = FileUtil.getFileExtensionFromName(file.getName()); mineType = MimeTypeUtil.getSingleton().getMimeTypeFromExtension(fileExtension); if (StringUtil.isNotEmpty(mineType)) { multipartEntity.addPart(entry.getKey(), new FileBody(file, mineType)); // 添加文件参数,带上mimeType } else { multipartEntity.addPart(entry.getKey(), new FileBody(file)); // 添加文件参数 } } httpEntityEnclosingRequest.setEntity(multipartEntity); } else { List<NameValuePair> stringParams = new ArrayList<NameValuePair>(); for (Map.Entry<String, Object> entry : httpRequestMessage.getParameters().entrySet()) { stringParams.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue()))); } UrlEncodedFormEntity entity = new UrlEncodedFormEntity(stringParams, "UTF-8"); httpEntityEnclosingRequest.setEntity(entity); } httpRequest = httpEntityEnclosingRequest; break; } Map<String, String> headers = httpRequestMessage.getHeaders(); if (headers != null && headers.size() > 0) { for (Map.Entry<String, String> entry : headers.entrySet()) { httpRequest.addHeader(entry.getKey(), entry.getValue()); } } return httpRequest; } /** * 设置Basic认证的头部信息 * * @param httpRequest * @param auth */ private static String getBasicAuthorizationHeader(BasicAuthorization auth) { String authHeader = ""; if (auth == null) { return authHeader; } String rawKeyPair = auth.getUserName() + ":" + auth.getPassword(); byte[] keyPairBytes = rawKeyPair.getBytes(); String keyPair = new String(Base64.encodeBase64(keyPairBytes)); authHeader = "Basic " + keyPair; return authHeader; } }