How to get query parameters from HttpServletRequest (Tomcat 9.0)? - java

The server recieves requests from two clients - Raspberry Pi and Android app, both send requests using HttpURLConnection. I need to pass parameters with theese requests, e.g:
http://192.168.0.10:8080/MyProject/MyServer/rpi/checktask?rpi="rpi"
doing it as:
String requestUrl = "http://192.168.0.10:8080/MyProject/MyServer/rpi";
String query = String.format("/checktask?rpi=%s",
URLEncoder.encode("rpi", "UTF-8"));
URL url = new URL(requestUrl + query);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.connect();
The Servlet has annotation:
#WebServlet(name = "MyServer", urlPatterns = { "/MyServer/rpi/*", "/MyServer/app/*"})
But when Servlet gets request as above following happens:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = request.getRequestURI(); // /MyProject/MyServer/rpi/*
String query = request.getQueryString(); // null
String context = request.getContextPath(); // /MyProject
String servlet = request.getServletPath(); // /MyServer/rpi
String info = request.getPathInfo(); // /*
}
Although according to those answers:
How to use #WebServlet to accept arguments (in a RESTFul way)?
and
How come request.getPathInfo() in service method returns null?
it should look like this:
String path = request.getRequestURI(); // /MyProject/MyServer/rpi//checktask?rpi="rpi"
String query = request.getQueryString(); // rpi="rpi"
String context = request.getContextPath(); // /MyProject
String servlet = request.getServletPath(); // /MyServer/rpi
String info = request.getPathInfo(); // /checktask?rpi="rpi"
What am I doing wrong?

Your URL string is
http://192.168.0.10:8080/MyProject/MyServer/rpi/checktask?rpi="rpi"
The name of the parameter in the above String is "rpi".
The below code will give you the required value of the parameter "rpi".
String rpi = request.getParameter("rpi");

Related

java http request Required String parameter 'Username' is not present

I have a spring boot server running that accepts http request.
I have tested it extensively with curl and it works perfectly.
However when I try to send a request and receive a response in a java client I get:
java.io.IOException: Server returned HTTP response code: 400 for URL:
and on the server side I get:
[org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'Username' is not present]
Here is the spring boot method I am trying to use:
#PostMapping(path="/CreateAccount") // Map ONLY POST Requests
public #ResponseBody String CreateUser (#RequestParam String Username
, #RequestParam String Password) {
// #ResponseBody means the returned String is the response, not a view name
// #RequestParam means it is a parameter from the GET or POST request
//make sure the username and password is valid input
if (!validateInput(Username) || !validateInput(Password))
{
return "Username and Password cannot be blank";
}
//make sure the username is unique
//check if Username is equal to any other User's username
User u = findByUsername(Username);
//if a user was found in the table
if ( !(u == null) )
{
return "Username already taken\nPlease choose another";
}
//if we are here we are clear to make a new user
User n = new User();
n.setUsername(Username);
n.setPassword(Password);
n.setRole("Player");
userRepository.save(n);
//THIS CAUSES AN ERROR
//create a stat object to be added to the table
Stats s = new Stats();
s.setUsername(Username);
statRepository.save(s);
//create a token for the user
String usrToken = createToken(tokenSize);
//add the username and token to hashmap
userTokens.put(Username, usrToken);
//return this user's token
return usrToken;
}
And here is my client:
public static void CreateAccount(String username, String password)
{
try
{
String s = serverURL + "/CreateAccount";
URL url = new URL(s);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json; utf-8");
connection.setDoOutput(true);
String json = "[{\n\"Username\"=\"Jake\",\"Password\"=\"123\"\n}]";
System.out.println(json);
OutputStream os = connection.getOutputStream();
DataOutputStream out = new DataOutputStream( os );
byte[] input = json.getBytes("utf-8");
out.writeUTF(json);
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response = br.readLine();
System.out.println(response);
}
catch (Exception e)
{
System.out.println("#");
System.out.println(e);
}
}
I thought it had to do with my json formatting but I've tried over and over and no matter how I format it I get the same error.
If you want send json object, use this code for example:
#PostMapping(path="/CreateAccount")
public #ResponseBody String CreateUser (#RequestBody User user) {
if (user == null)
{
return "User cannot be blank";
}
User u = findByUsername(user.Username);
// your code...
return usrToken;
}

Retrieve parameters in a servlet with a JDBC client

I have a JDBC client calling a servlet.
Here's my client :
String query = "select * FROM Table";
int port = 8080;
String user = "user";
String password = "passwd";
String jdbcAvaticaURL = "jdbc:avatica:remote:url=http://localhost:"+port+";authentication=BASIC;serialization=JSON";
Connection connection = DriverManager.getConnection(jdbcAvaticaURL, user, password); // ,info);
executeQuery(connection,query);
connection.close();
And here's my servlet :
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getParameter("user"); // returns NULL
Enumeration<String> params = request.getParameterNames(); // Empty Collection
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
// DO THINGS
}
is there a way to retrieve the user and password from DriverManager.getConnection(jdbcAvaticaURL, user, password); in the servlet ?
I already tried String auth = request.getHeader("Authorization"); when I put the parameters in the JDBC URL, it's working, I can retrieve the user and the password, but this is not what I want.
It's fine, after trying to get the attributes, parameters, etc... of the request, turns out the credentials were just in the request...
Doing this in the servlet let me access the user and password used for the connection in the client (after some JSON parsing) :
String myRequest = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));

Servlet equivalent in Python?

On client side , following android code would make the call to the local server :
String link = "http://localhost:8080/test/cgi-bin/test.py";
URL url = null;
try {
url = new URL(link);
HttpURLConnection client = (HttpURLConnection) url.openConnection();
JSONObject jo = new JSONObject();
jo.put("desc","xyz");
String data2 = jo.toString();
client.setRequestMethod("Post");
// client.setRequestProperty("key","value");
client.setDoOutput(true);
OutputStreamWriter outputPost = new OutputStreamWriter(client.getOutputStream());
outputPost.write(data2);
outputPost.flush();
outputPost.close();
Earlier I was using servlets to interact with DB as the code below :
Using HttpServlet class , i could get the request and its parameters :
public class ServletXYZ extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String method = request.getParameter("method");
Is there any way in python which allows me to do the same (getting parameter values from request) ?
Thanks.
I've used CherryPy as a general purpose HTTP server framework. Ultimately to do the same as the servlet, there are many links - this one seems to be pretty much what you want.

Java Servlet Requesting Data From Local Service

In a Java HttpServlet, is it possible to request data from another local service using the original request's header information without necessarily forwarding?
For example, I have FooBar.java:
// Handles the url at /foo/bar and can be accessed at http://localhost/foo/bar
public class FooBar extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Object data = ... // 1. Retrieve data at http://localhost/foo/baz utilizing the current request's header
Object newData = doSomething(data); // 2. Process the data
response.getWriter().write(newData.toString); // 3. Return the processed data
}
private Object doSomething(Object data)
{
// Perform some business logic
}
}
Step 1 is the issue here. The purpose of this is that I want to be able to perform some sort of logic on the data before returning it in full, but don't necessarily have access do make the changes on the handler at /foo/baz do to the propriety nature of things.
You can use this answer of me to create a HTTP Request: send get request
In addition, it may be necessary to copy the request header with some care:
private static final Set forbiddenCopyHeaders = new HashSet<>(Arrays.asList(new String[]{
"connection"
, "transfer-encoding"
, "content-length" // POST kann zu Status 500 führen, wenn die content-length kopiert wird
, "via"
, "x-forwarded-for"
, "x-forwarded-host"
, "x-forwarded-server"
}));
private void copyRequestHeaders(HttpServletRequest customerRequest, HttpRequestBase internRequest) throws
HttpException
{
Enumeration<String> headerNames = customerRequest.getHeaderNames();
String connectionHeader = customerRequest.getHeader("connection");
while (headerNames.hasMoreElements())
{
String headerName = headerNames.nextElement();
boolean copyAllowed = !forbiddenCopyHeaders.contains(headerName.toLowerCase()) &&
!StringUtils.containsIgnoreCase(connectionHeader, headerName);
if (copyAllowed)
{
Enumeration<String> values = customerRequest.getHeaders(headerName);
while (values.hasMoreElements())
{
internRequest.addHeader(headerName, values.nextElement());
}
}
}
setProxySpecificRequestHeaders(customerRequest, internRequest);
}
private void setProxySpecificRequestHeaders(HttpServletRequest customerRequest,
HttpRequestBase internRequest) throws HttpException
{
String serverHostName = "doorman";
try
{
serverHostName = InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException e)
{
logger.error("Couldn't get the hostname needed for headers x-forwarded-server and Via", e);
}
String originalVia = customerRequest.getHeader("via");
StringBuilder via = new StringBuilder("");
if (originalVia != null)
{
if (originalVia.contains(serverHostName))
{
logger.error("This proxy has already handled the Request, will abort.");
throw new HttpException("Request has a cyclic dependency on this proxy.");
}
else
{
via.append(originalVia).append(", ");
}
}
via.append(customerRequest.getProtocol()).append(" ").append(serverHostName);
internRequest.addHeader("via", via.toString());
internRequest.addHeader("x-forwarded-for", customerRequest.getRemoteAddr());
internRequest.addHeader("x-forwarded-host", customerRequest.getServerName());
internRequest.addHeader("x-forwarded-server", serverHostName);
internRequest.addHeader("accept-encoding", "");
}
Using HttpURLConnection and altering the header to include a property from the original request, I was able to get a BufferedReader from the HTTP request:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// Step 1
String serverName = request.getLocalName();
String contextPath = request.getContextPath();
URL url = new URL("https://" + serverName + contextPath + "/baz");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Key Header", request.getHeader("Key Header"));
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
// Step 2
... // Do something with the data from the reader
// Step 3
... // Write the data back using the response
}

Google App Engine - Updating a blobstore via byte array using simulated POST

I'm getting the following exception when I try to simulate a post request to upload to the app engine blobstore using Java:
WARNING: /_ah/login
java.lang.NullPointerException
at com.google.appengine.api.users.dev.LoginCookieUtils.encodeEmailAsUserId(LoginCookieUtils.java:89)
at com.google.appengine.api.users.dev.LoginCookieUtils.createCookie(LoginCookieUtils.java:41)
at com.google.appengine.api.users.dev.LocalLoginServlet.doPost(LocalLoginServlet.java:90)
Here's is the code that is doing the POST request:
byte[] htmlData = // ...I already have the byte array I want to store/update)
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
String uploadURL = blobstoreService.createUploadUrl("/upload");
//add host if in dev mode
if(uploadURL.indexOf("http") == -1)
{
uploadURL = "http://localhost:8888" + uploadURL;
}
URL url = new URL(uploadURL);
// create a boundary string
String boundary = MultiPartFormOutputStream.createBoundary();
URLConnection urlConn = MultiPartFormOutputStream.createConnection(url);
urlConn.setReadTimeout(15000);
urlConn.setRequestProperty("Accept", "*/*");
urlConn.setRequestProperty("Content-Type", MultiPartFormOutputStream.getContentType(boundary));
// set some other request headers...
urlConn.setRequestProperty("Connection", "Keep-Alive");
urlConn.setRequestProperty("Cache-Control", "no-cache");
// no need to connect because getOutputStream() does it
MultiPartFormOutputStream out = new MultiPartFormOutputStream(urlConn.getOutputStream(), boundary);
out.writeField("param", "value")
out.writeFile("myFile", "multipart/form-data", "content.html", htmlData);
out.close();
Then in upload.java
public class Upload extends HttpServlet
{
private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
Map<String, BlobKey> blobs = blobstoreService.getUploadedBlobs(req);
BlobKey blobKey = blobs.get("myFile");
String value = req.getParameter("param");
Topic t = pm.getObjectById(Topic.class, key);
t.setParam("value");
try
{
pm.makePersistent(t);
}
....
Why am I getting an exception for encodeEmailAsUserId?
P.S. The writeFields persist and update just fine in the Datastore, but I still get this exception.
I figured out the solution to this. The problem is that the example I pulled the MultiPartStream code from did not set the header for the authentication cookie.
I simply added the following to my middle-man servlet that passes the Post data off to the Upload servlet.
Cookie [] cookies = req.getCookies();
String name = cookies[0].getName();
String value = cookies[0].getValue();
...
urlConn.setRequestProperty("Cookie", name + "=" + value);

Categories