I have been playing around with Java httpServer class a little bit. When I run my test application it will get to the last line (a println) in main about right a way, but then it sits there for about 45 secs before closing the application. Why does it do that and is there a way to make it so it ends faster? Thanks
public class TestTester
{
public static void main(String[] args) throws IOException {
InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 8780);
HttpServer server = HttpServer.create(addr, 0);
server.createContext("/", new MyHandler());
server.setExecutor(Executors.newCachedThreadPool());
server.start();
URL url = new URL("http://localhost:8780/test");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStreamReader(connection.getInputStream()));
// print out the response headers
System.out.println("\nHttp Response Headers");
for (int i=0; ; i++)
{
String headerName = connection.getHeaderFieldKey(i);
String headerValue = connection.getHeaderField(i);
if (headerName == null && headerValue == null) {
// No more headers
break;
}
else if (headerName == null) {
System.out.println( " " + headerValue);
}
else
System.out.println( " " + headerName + ": " + headerValue );
}
connection.disconnect();
server.stop(0);
System.out.println("Stopped Server.");
} // end main()
}
class MyHandler implements HttpHandler {
#Override
public void handle(HttpExchange exchange) throws IOException
{
System.out.println("===Enter MyHandler===");
System.out.println("Http Request Header:");
// print out the request methode and url
System.out.println( " " + exchange.getRequestMethod() + " "
+ exchange.getRequestURI() + " " + exchange.getProtocol());
// print out the request headers
Headers requestHeaders = exchange.getRequestHeaders();
for (String name : requestHeaders.keySet() )
{
List<String> values = requestHeaders.get(name);
for ( String value : values )
{
System.out.println( " " + name + ": " + value);
}
}
// print out the request body if any
BufferedReader in = new BufferedReader(new InputStreamReader(exchange.getRequestBody()));
String sCurrentLine;
System.out.println( "\nHttp Request Body:");
if ( ! in.ready() )
System.out.println( " No Request Body");
else
{
while ((sCurrentLine = in.readLine()) != null) {
System.out.println(" " + sCurrentLine);
}
}
// set up and send response
String requestMethod = exchange.getRequestMethod();
if (requestMethod.equalsIgnoreCase("GET"))
{
Headers responseHeaders = exchange.getResponseHeaders();
responseHeaders.set("Content-Type", "text/html");
exchange.sendResponseHeaders(200, 0);
OutputStream responseBody = exchange.getResponseBody();
responseBody.write("<!DOCTYPE html><html><body><h1>My Response Header</h1><p>And some sample data.</p></body></html>".getBytes());
responseBody.close();
}
exchange.close();
} // end public void handle()
} // end class
I did find something that seems to work although I am not sure if it is the correct way to be handling this. This is not extensively tested, but it does make it shutdown faster.
I replaced:
server.setExecutor(Executors.newCachedThreadPool());
With:
ExecutorService excu = Executors.newCachedThreadPool();
server.setExecutor(excu);
Then just before the server.stop(0); I added excu.shutdown();
Related
I am developing a custom log with Spring MVC to get information from all incoming request. I would like to grab both the request body and response body. The issue is, even if I create a HttpServletRequestWrapper, I cannot forward the request after I process and wrap the request.
Here is my code:
Interceptor
#Component
public class LoggerInterceptor implements HandlerInterceptor{
final static org.apache.log4j.Logger log = Logger.getLogger(LoggerInterceptor.class.getName());
/**
* Executed before actual handler is executed
**/
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
long start = System.currentTimeMillis();
MyRequestWrapper requestWrapper = new MyRequestWrapper(request);
SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
String date = f.format(new Date());
UUID uuid = UUID.randomUUID();
String method = requestWrapper.getMethod();
String uri = requestWrapper.getRequestURI();
String step = "Default Step";
String url = String.valueOf(requestWrapper.getRequestURL());
String serverName = requestWrapper.getServerName();
String reqBody = IOUtils.toString(requestWrapper.getInputStream(), Charset.forName("UTF-8").toString());
CustomHttpResponseWrapper responseWrapper = new CustomHttpResponseWrapper(response);
long end = System.currentTimeMillis() - start;
String status = String.valueOf(responseWrapper.getStatus());
String resBody = new String(responseWrapper.getBaos().toByteArray());
if(step!=null && !step.isEmpty()) {
log.info("INFO " + date + " " + uuid + "\n" +
"ID : " + getCurrentlyDateTime() + "\n" +
"STEP : " + step + "\n" +
"Request URL: " + url + "\n" +
"Host : " + serverName + "\n" +
"Request Body : " + reqBody + "\n" +
"Response Status : " + status + "\n" +
"Response Body : " + resBody + "\n" +
"Response Time : " + end);
}
return true;
}
}
Request Wrapper
public class MyRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public MyRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
#Override
public boolean isFinished() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isReady() {
// TODO Auto-generated method stub
return false;
}
#Override
public void setReadListener(ReadListener readListener) {
// TODO Auto-generated method stub
}
};
return servletInputStream;
}
#Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
}
Output
INFO 2022/04/12 10:35:18:578 d00ec778-2a6e-4a72-a0e0-9649c13776eb
ID : 20220412103518
STEP : Default Step
Request URL: http://localhost:8080/com.ihcs.api.mobile/loginNew
Host : localhost
Request Body : {
"username":"P0****",
"sessionid":"*************************",
"password":"********",
"companyCode":"***",
"UniqueId":"**********",
"Manufacturer":"google",
"Brand":"google",
"Model":"*******",
"DeviceId":"*******",
"FcmTokens":"*******",
"UniqueLogin":false
}
Response Status : 200
Response Body :
Response Time : 18
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is java.io.IOException: Stream closed
I've tried some suggestions from stack overflow but still can't help. Thank you.
I am using littleproxy-mitm to proxy requests in java to remote servers, yet I am getting an empty response from curl when trying to make a request through the proxy, regardless if it is http or https:
curl: (52) Empty reply from server
curl: (56) Proxy CONNECT aborted
My code:
HttpProxyServer server =
DefaultHttpProxyServer.bootstrap()
.withPort(PORT)
.withManInTheMiddle(new CertificateSniffingMitmManager())
.withFiltersSource(new HttpFiltersSourceAdapter() {
public HttpFilters filterRequest(HttpRequest originalRequest, ChannelHandlerContext context) {
System.out.println("-----------------------------------------------------");
HttpMethod method = originalRequest.getMethod();
String originalUri = originalRequest.getUri();
System.out.println("CLIENT " + method + " -> " + originalUri);
originalRequest.headers().forEach(entry -> {
System.out.println("-- " + entry.getKey() + ":" + entry.getValue());
});
if (HttpMethod.CONNECT.equals(method) && Objects.nonNull(context) && originalUri.endsWith(":443")) {
String url = "https://" + originalUri.replaceFirst(":443$", "");
context.channel().attr(CONNECTED_URL).set(url);
System.out.println("URL: " + context.channel().attr(CONNECTED_URL).get());
System.out.println("(Manipulating connection request for successful HTTPS: " + originalUri + " -> " + url + ")");
return new HttpFiltersAdapter(originalRequest, context);
}
return new HttpFiltersAdapter(originalRequest) {
#Override
public HttpResponse clientToProxyRequest(HttpObject httpObject) {
if (httpObject instanceof LastHttpContent) {
LastHttpContent copy = ((LastHttpContent) httpObject).copy();
String body = copy.content().toString(StandardCharsets.UTF_8);
System.out.println("-- Content:" + body);
}
return null;
}
#Override
public HttpObject serverToProxyResponse(HttpObject httpObject) {
System.out.println("Server Response");
if (httpObject instanceof HttpResponse) {
HttpResponse response = (HttpResponse) httpObject;
System.out.println("SERVER RESPONSE");
response.headers().forEach(entry -> {
System.out.println("-- " + entry.getKey() + ":" + entry.getValue());
});
}
return httpObject;
}
};
}
})
.start();
I'm trying to send cookies to the server, but it doesn't work. Please tell me thats wrong. Here is my code.
At first, I take cookie in the POST request.
> Map <String, List<String>> headerFields = postRequest.getHeaderFields();
> List<String> cookiesHeader = headerFields.get("Set-Cookie");
Later, in the GET request, i'm send cookie to the server.
getRequest.setRequestProperty("Cookie", cookiesHeader.toString());
Help me. I'm beginner, not judge strictly.
Here all my code.
#Override
protected String doInBackground(Void... params) {
Log.i(TAG, "doInBackground");
String store_id = "";
final String COOKIES_HEADER = "Set-Cookie";
final String COOKIE = "Cookie";
try {
Thread.sleep(4000);
Log.i(TAG, "httpRequest start");
String parametrs = mPhone.getText().toString();
String parametrs2 = mPass.getText().toString();
JSONObject allParams = new JSONObject();
HttpURLConnection postRequest = null;
InputStream inputStream = null;
byte[] data = null;
try {
URL serverUrl = new URL("https://api.fianitlombard.ru/mobile/auth");
postRequest = (HttpURLConnection) serverUrl.openConnection();
postRequest.setReadTimeout(10000 /* milliseconds */);
postRequest.setConnectTimeout(15000 /* milliseconds */);
postRequest.setRequestMethod("POST");
postRequest.setDoInput(true);
postRequest.setDoOutput(true);
postRequest.setRequestProperty("Content-Type", "application/json; charset=utf-8");
postRequest.connect();
allParams.put("phone", parametrs);
allParams.put("password", parametrs2);
Log.i(TAG, "allParams" + allParams);
OutputStream bos = (postRequest.getOutputStream());
bos.write(allParams.toString().getBytes());
String helpInfo = postRequest.getResponseMessage();
Log.i(TAG, "helpInfo =" + helpInfo);
responseCode = postRequest.getResponseCode();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Map<String, List<String>> headerFields = postRequest.getHeaderFields();
List<String> cookiesHeader = headerFields.get(COOKIES_HEADER);
if (responseCode == 200) {
inputStream = postRequest.getInputStream();
byte[] buffer = new byte[8192]; // Такого вот размера буфер
// Далее, например, вот так читаем ответ
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
data = baos.toByteArray();
resultString = new String(data, "UTF-8");
Log.i(TAG, "responseCode = " + responseCode);
Log.i(TAG, "resultCode = " + resultString);
JSONObject jsonObject = new JSONObject(resultString);
store_id = jsonObject.getString("store_id");
Log.i(TAG, "store_id =" + store_id);
bos.close();
baos.close();
postRequest.disconnect();
}
if (responseCode == 403) {
Log.i(TAG, "responseCode = " + responseCode);
}
HttpURLConnection getRequest = null;
try {
URL serverUrl1 = new URL("https://api.fianitlombard.ru/mobile/checksession?version=1.0.8");
URI uri = URI.create("https://api.fianitlombard.ru/mobile/checksession?version=1.0.8");
getRequest = (HttpURLConnection) serverUrl1.openConnection();
getRequest.setReadTimeout(20000 /* milliseconds */);
getRequest.setConnectTimeout(25000 /* milliseconds */);
getRequest.setRequestMethod("GET");
getRequest.setRequestProperty("Content-Type", "application/json; charset=utf-8");
getRequest.setRequestProperty(COOKIE, cookiesHeader.toString());
Log.i(TAG, "Cookie = " + cookiesHeader.toString());
getRequest.connect();
int responceGetCode = getRequest.getResponseCode();
String responceGetInfo = getRequest.getResponseMessage();
Log.i(TAG, "responceGetCode = " + responceGetCode);
Log.i(TAG, "responceGetInfo = " + responceGetInfo);
if (responceGetCode == 200) {
//Все хорошо
}
if (responceGetCode == 400) {
// Устарела версия, нужно обновление
}
if (responceGetCode == 403) {
//Проблемы с авторизацией
} else {
//Что то другое.
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (getRequest != null)
getRequest.disconnect();
}
} catch (IOException e1) {
e1.printStackTrace();
}
if (postRequest != null) {
postRequest.disconnect();
}
Log.i(TAG, "httpRequest end");
}
catch (InterruptedException | JSONException e) {
e.printStackTrace();
}
return store_id;
}
change below line
getRequest.setRequestProperty(COOKIE, cookiesHeader.toString());
to
getRequest.setRequestProperty( COOKIE, cookiesHeader.get( 0 ) );
toString() method of List will return the hashCode() but not the actual values of List
try to use the following method to get the cookie :
String getHeaderField("Set-Cookie")
you set the cookie by using the lists toString method, which will not give you the current cookie representation, but instead a string matching "[var1, var2, var3]"
The server sends the following in its response header to set a cookie field.
Set-Cookie:name=value
If there is a cookie set, then the browser sends the following in its request header.
Cookie:name=value
See the HTTP Cookie article at Wikipedia for more information.
i'm trying to add the following headers to a rest Post call... it works in plain Java but i'm trying to re-write it using the Jersey client library... When I make the post with Jersey I get an error code which isn't listed in the API documentation so i know it must just be a small issue like a missing header... Any idea what i'm doing wrong in the bottom function?
Plain Java add headers function that works:
private void SetDefaultHeaders(HttpURLConnection conn) {
setRequestProperty(conn, "Accept", "*");
setRequestProperty(conn, "Content-Type", "application/x-www-form-urlencoded");
}
Jersey code:
public void logIn(String email, String password) {
if (email != "" && email != null && password != "" && password != null) {
try {
StringBuilder sb = new StringBuilder();
sb.append(Settings.WIFIPLUG_URL);
sb.append("/user_login");
MultivaluedMap<String, String> body = new MultivaluedMapImpl();
body.add("username=", email);
body.add("password=", password);
System.out.println("login url: " + sb.toString());
WebResource webResource = Client.create(new DefaultClientConfig()).resource(sb.toString());
WebResource.Builder builder = webResource.accept("*");
builder.type("application/x-www-form-urlencoded");
ClientResponse response = builder.post(ClientResponse.class, body);
if (response.getStatus() != 200) {
throw new RuntimeException("failed: http error code " + response.getStatus());
}
System.out.println("Response from server: " + response.getEntity(String.class));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Full vanilla java login function:
public String postUserLogin(String username, String password) {
String result = "";
// URL for API to login
String url = "https://wifiplugapi.co.uk:3081/zcloud/api/user_login";
String requestParams = "username=" + username + "&password=" + password;
try {
URL obj = new URL(url);
System.out.println("login url: " + obj);
// Opens the connection
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
// Send POST request
con.setDoOutput(true);
con.setDoInput(true);
// Request Headers
con.setRequestMethod("POST");
// Sets all the headers
SetDefaultHeaders(con);
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
wr.write(requestParams);// adds values to the request
wr.flush();
wr.close();
// Handles the response
StringBuilder sb = new StringBuilder();
int responseCode = con.getResponseCode();
if (responseCode == 200) {
// if the request was successful OK = 200
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
// Returns Token
} else {
// If the request was bad, reason will be printed
result = "Error, login request failed";
throw new RuntimeException("Failed : HTTP error code : " + con.getResponseCode());
}
result = sb.toString();
// JSON Parser
JsonParser parser = new JsonParser();
JsonObject resultObj = parser.parse(result).getAsJsonObject();
con.disconnect();
if (resultObj.get("token") != null) {
result = (resultObj.get("token")).toString();
System.out.println("JSONObject Result (token): " + result);
} else {
System.out.println("result = " + result);
}
} catch (Exception e) {
e.printStackTrace();
}
// returns token value in string ie. fdg573gb3789gv923378gy83g3
result = result.replaceAll("\"", "");
return result;
}
You shouldn't have the = in the key when doing body.add. It will be added for you
MultivaluedMap<String, String> body = new MultivaluedMapImpl();
body.add("username=", email); // remove the =
body.add("password=", password); // remove the =
I am trying to connect with Tomcat Server(IP address-192.168.1.120 which is stored in Config.java(static variable APP_SERVER_URL)) but it is giving me socket timeout exception .
How to resolve it.Please help.
But when I
public class ShareExternalServer {
public String shareRegIdWithAppServer(Map<String, String> paramsMap) {
String result = "";
try {
URL serverUrl = null;
try {
serverUrl = new URL(Config.APP_SERVER_URL);
} catch (MalformedURLException e) {
Log.e("AppUtil", "URL Connection Error: "
+ Config.APP_SERVER_URL, e);
result = "Invalid URL: " + Config.APP_SERVER_URL;
}
StringBuilder postBody = new StringBuilder();
Iterator<Entry<String, String>> iterator = paramsMap.entrySet()
.iterator();
while (iterator.hasNext()) {
Entry<String, String> param = iterator.next();
postBody.append(param.getKey()).append('=')
.append(param.getValue());
if (iterator.hasNext()) {
postBody.append('&');
}
}
String body = postBody.toString();
Log.d("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&",body);
byte[] bytes = body.getBytes();
HttpURLConnection httpCon = null;
try {
httpCon = (HttpURLConnection) serverUrl.openConnection();
httpCon.setDoOutput(true);
httpCon.setUseCaches(false);
httpCon.setFixedLengthStreamingMode(bytes.length);
httpCon.setRequestMethod("POST");
httpCon.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
httpCon.setConnectTimeout(20000);
OutputStream out = httpCon.getOutputStream();
out.write(bytes);
out.close();
int status = httpCon.getResponseCode();
Log.d("$$$$$$$$$$$$$$$$$$",String.valueOf(status));
/* if (status == 200) {
result = "RegId shared with Application Server. RegId: "
+ regId;
} else {
result = "Post Failure." + " Status: " + status+regId;
}*/
} finally {
if (httpCon != null) {
((HttpURLConnection) httpCon).disconnect();
}
}
} catch (IOException e) {
result = "Post Failure. Error in sharing with App Server.";
Log.e("AppUtil", "Error in sharing with App Server: " + e);
}
return result;
}
}