Created
June 27, 2019 14:40
-
-
Save danghica/23b020b8125e1a050e860814b8d1623a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public final class XWWWFormUrlencodedHTTPRequest extends HashMap<String, String> { | |
private static final long serialVersionUID = 0xe673f874cf17d539L; | |
public XWWWFormUrlencodedHTTPRequest(URL url, Object... params) | |
throws IOException, IllegalArgumentException { | |
this(url, evenLengthListToMap(params)); | |
} | |
@SuppressWarnings("LeakingThisInConstructor") | |
public XWWWFormUrlencodedHTTPRequest(URL url, Map<String, String> params) | |
throws IOException, MisencodedResponseException, | |
IllegalArgumentException { | |
super(); | |
URLConnection c = url.openConnection(); | |
if (!(c instanceof HttpURLConnection)) { | |
throw new IllegalArgumentException("URL " + url + " is not an HTTP URL"); | |
} | |
HttpURLConnection hc = (HttpURLConnection) c; | |
hc.setDoOutput(true); | |
hc.setRequestMethod("POST"); | |
hc.setRequestProperty("Content-Type", "x-www-form-urlencoded; charset=UTF-8"); | |
hc.connect(); | |
try { | |
try (OutputStream os = hc.getOutputStream()) { | |
os.write(urlEncodeMap(params).getBytes("UTF-8")); | |
} | |
switch (hc.getResponseCode()) { | |
case HttpURLConnection.HTTP_OK: | |
try (InputStream is = hc.getInputStream()) { | |
decodeInputStream(is, this); | |
} catch (XWWWFormUrlencodedHTTPHandler.HTTPResponseException ex) { | |
throw new MisencodedResponseException(ex.getCause()); | |
} | |
break; | |
case HttpURLConnection.HTTP_NO_CONTENT: | |
case HttpURLConnection.HTTP_RESET: | |
/* These indicate success, but that no data was returned. | |
So we just continue to act as an empty map. */ | |
break; | |
default: | |
throw new FailureOnServerException(hc.getResponseCode()); | |
} | |
} finally { | |
hc.disconnect(); | |
} | |
} | |
public String returnValue(String key) throws MisencodedResponseException { | |
if (containsKey(key)) { | |
return get(key); | |
} else { | |
throw new MisencodedResponseException( | |
"HTTP response did not contain key '" + key + "'"); | |
} | |
} | |
public String nullableReturnValue(String isPresentKey, String valueKey) | |
throws MisencodedResponseException { | |
String isPresent = returnValue(isPresentKey); | |
switch (isPresent) { | |
case "true": | |
return returnValue(valueKey); | |
case "false": | |
return null; | |
default: | |
throw new MisencodedResponseException("Return value '" | |
+ isPresentKey + "' is neither 'true' nor 'false'"); | |
} | |
} | |
@SuppressWarnings("UseSpecificCatch") | |
public <T, X extends Exception> T decodeReturnValue( | |
String key, XWWWFormUrlencodedHTTPHandler.ExceptionFunction<String, T, X> decoder, | |
Class<X> exception) throws MisencodedResponseException { | |
String param = returnValue(key); | |
try { | |
return decoder.apply(param); | |
} catch (RuntimeException ex) { | |
if (exception.isAssignableFrom(ex.getClass())) { | |
throw new MisencodedResponseException( | |
"Could not decode return value '" + key + "'", ex); | |
} | |
throw ex; | |
} catch (Exception ex) { | |
throw new MisencodedResponseException( | |
"Could not decode return value '" + key + "'", ex); | |
} | |
} | |
private static Map<String, String> evenLengthListToMap(Object[] list) | |
throws IllegalArgumentException { | |
Map<String, String> rv = new HashMap<>(); | |
if ((list.length % 2) != 0) { | |
throw new IllegalArgumentException("list has odd length"); | |
} | |
for (int i = 0; i < list.length; i += 2) { | |
if (list[i] instanceof String) { | |
rv.put((String) list[i], list[i + 1].toString()); | |
} else { | |
throw new IllegalArgumentException("list element " + i | |
+ " is not a String"); | |
} | |
} | |
return rv; | |
} | |
public static class FailureOnServerException extends IOException { | |
private static final long serialVersionUID = 0x89865f72fc9de35fL; | |
public FailureOnServerException(int code) { | |
super("HTTP connection failed with code " + code); | |
} | |
} | |
public static class MisencodedResponseException extends IOException { | |
private static final long serialVersionUID = 0x3799ea05e2f3f5f6L; | |
public MisencodedResponseException(Throwable cause) { | |
super(cause); | |
} | |
public MisencodedResponseException(String message) { | |
super(message); | |
} | |
public MisencodedResponseException(String message, Throwable cause) { | |
super(message, cause); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment