This question already has answers here:
Why does my JavaScript code receive a "No 'Access-Control-Allow-Origin' header is present on the requested resource" error, while Postman does not?
(13 answers)
CORS Java server side implementation
(2 answers)
No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API
(26 answers)
Closed last year.
I'm trying to make a server in java that can handle requests sent from the browser. My problem is that I can't get the browser to actually send the request, all it sends is an OPTIONS request. Here's the error in the browser:
It isn't an actual website that I'm using, it's just an html page that would be opened by the java application. Here's the html:
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="sendRequest()">Click Me!</button>
<script>
function sendRequest() {
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://172.26.48.1:9000/test", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify({
"time": 16400
}));
}
</script>
</body>
</html>
And here's the java server that listens for the requests:
public class ServerTest
{
public static void main(String[] args) throws Exception
{
HttpServer server = HttpServer.create(new InetSocketAddress(9000), 0);
server.createContext("/test", new MyHandler());
server.setExecutor(null);
server.start();
}
static class MyHandler implements HttpHandler
{
public void handle(HttpExchange exchange) throws IOException
{
System.out.println("Handling request: " + exchange.getRequestMethod());
if (exchange.getRequestMethod().equalsIgnoreCase("POST") ||
exchange.getRequestMethod().equalsIgnoreCase("OPTIONS"))
{
try
{
InputStream is = exchange.getRequestBody();
StringBuilder sb = new StringBuilder();
for (int ch; (ch = is.read()) != -1;)
sb.append((char) ch);
System.out.println(sb.toString());
String response = "OK";
exchange.sendResponseHeaders(200, response.length());
OutputStream os = exchange.getResponseBody();
os.write(response.getBytes());
os.close();
exchange.close();
} catch (NumberFormatException e)
{
e.printStackTrace();
}
}
}
}
}
The server works fine, but it only receives the OPTIONS request. How can I make the html page send the actual POST request?
function sendRequest() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "http://172.26.48.1:9000/test", true);
xhttp.setRequestHeader("Content-Type", "application/json");
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Response
var response = this.responseText;
}
};
xhttp..send(JSON.stringify({
"time": 16400
}));
}
Related
I have two applications: one web client and one java server. The web client sends an HTTP POST request with a JSON body of data, and the server should receive the data and display it on the screen. The problem is that when the server reads the body of the request, there is nothing to read. What is wrong?
Edit: I realized that the problem is on the browser side (since I could send and read an HTTP POST request from some other website), but I still don't know what the problem is. Is this related to the browser running the code? When I use Chrome I get the described problem. When I use Firefox or IE the java server isn't even notified; it doesn't even run the handle method that is supposed to run when it gets an HTTP request.
It worked to read data at the server when I coded the content type as url encoded. I think it was: x-www-form-urlencoded. But I want to send data as JSON.
I use XMLHttpRequest for the web client, as you can see below.The web client:
<!DOCTYPE html>
<html>
<body>
<script>
function handleInput(){
var title = "title";
var reviewer = "reviewer";
const xhr = new XMLHttpRequest();
var searchInfo = {
title:title,
reviewer:reviewer
};
xhr.open('POST', 'http://localhost:8001');
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(JSON.stringify(searchInfo));
}
</script>
</body>
</html
The server:
import java.io.IOException;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class Server {
public static void main(String[] args) {
try {
HttpServer server = HttpServer.create(new InetSocketAddress("localhost", 8001), 0);
HttpHandler handler = new MyHttpHandler();
HttpContext context = server.createContext("/");
context.setHandler(handler);
server.start();
System.out.println("Server started on port 8001");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
The servers HTTP handler:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
public class MyHttpHandler implements HttpHandler {
#Override
public void handle(HttpExchange httpExchange) throws IOException {
InputStream is = httpExchange.getRequestBody();
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
StringBuilder content = new StringBuilder();
String line;
while ((line = br.readLine()) != null) { br.readLine is always null!!!
content.append(line);
content.append("\n");
}
System.out.println("Content: " + content.toString());
}
}
As your server (java side, live in localhost:8001) and client (xhttp side, live in somewhere else) are separated. The request is considered as cross origin requests (CORs).
There are 2 types of cross origin requests - Safe and unsafe:
Only the below Content-Type are considered as SAFE in cross site request:
application/x-www-form-urlencoded
multipart/form-data
text/plain
So, application/json; is considered UNSAFE.
For safe request, there is not much restriction on server so you can get the response back while using application/x-www-form-urlencoded
client <=> POST request <=> Server
For unsafe request, there is a preflight request (a special OPTIONS action) to ask the server
if client origin is allowed and
what can the client do
before making the real request, in your case the POST request.
client <=> pre-flight (OPTIONS) request <=> Server
client <=> POST request <=> Server
So the problem is there is no handling of preflight request and the request cannot be processed by server.
To deal with it, you need to change your handler as follow:
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
public class MyHttpHandler implements HttpHandler {
#Override
public void handle(HttpExchange httpExchange) throws IOException {
Headers headers = httpExchange.getResponseHeaders();
System.out.println(httpExchange.getRequestMethod());
headers.add("Access-Control-Allow-Origin", "*"); // * means allow all origin, in production, it should be the origin you trust e.g. http://client.abc.com
if (httpExchange.getRequestMethod().equalsIgnoreCase("OPTIONS")) {
headers.add("Access-Control-Allow-Headers", "Content-Type"); // allow clients to pass in content-type
headers.add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
httpExchange.sendResponseHeaders(204, -1);
return;
}
InputStream is = httpExchange.getRequestBody();
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
StringBuilder content = new StringBuilder();
String line;
while ((line = br.readLine()) != null) { // br.readLine is always null!!!
content.append(line);
content.append("\n");
}
System.out.println("Content: " + content.toString());
// added response as well to complete the request
String response = "Good" ;
httpExchange.sendResponseHeaders(200, response.length());
OutputStream os = httpExchange.getResponseBody();
os.write(response.getBytes(StandardCharsets.UTF_8));
os.close();
httpExchange.close();
}
}
HTML
<!DOCTYPE html>
<html>
<body>
<button onclick="handleInput()">Click</button>
<script>
function handleInput() {
var title = "title";
var reviewer = "reviewer";
const xhr = new XMLHttpRequest();
xhr.onload = function() {
console.log('done')
}
var searchInfo = {
title: title,
reviewer: reviewer,
};
xhr.open("POST", "http://localhost:8001");
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
xhr.send(JSON.stringify(searchInfo));
}
</script>
</body>
</html>
To further understanding CORs:
https://javascript.info/fetch-crossorigin
For your html
<form name="searchForm" id="searchForm" onSubmit="handleInput(event)">
...
</form>
<script>
function handleInput(e){
e.preventDefault()
...
}
</script>
I'm trying to send JSON data from a JavaScript function using Ajax to a Servlet.
Client side:
function addObject() {
var data = {
aa: "aa",
bb: "bb"
}
var string = JSON.stringify(data);
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "GalleryAdd", true);
xhttp.setRequestHeader("Content-Type", "application/json");
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
console.log("Done");
}
};
console.log(string);
xhttp.send(string);
}
Output from stringyfied data is {"aa":"aa","bb":"bb"}.
Servlet:
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
log(request.getParameter("aa"));
log(request.getParameter("bb"));
}
Output in the logger is null and null.
Looks like JavaScript does not send data to the servlet, also if it's stringifyed correctly. Anyone?
Your Json object is in the body of the request therefore you need to parse the InputStream. Try this.
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
JsonObject object = Json.createReader(req.getInputStream()).readObject();
log(object.getString("aa"));
log(object.getString("bb"));
}
Im currently working in MVC and I have what I see as crude ways of catching response and request headers on my pages.
First is Response headers which I currently handle on the page
$(document).ready(function () {
var name = "Comp";
var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var myHeader = req.getResponseHeader(name);
alert(myHeader);
});
it makes a new request when the document is ready which could ruin the header if it isn't pretty static (wouldn't work if the header were to change between the sessions) but it currently workes.
I do catch the Request header inside of the controller
public new ActionResult Profile()
{
var head = Request.Headers.GetValues("Comp");
try
{
if (head != null)
{
string id = head.First();
ViewBag.message = head.First(); //controll
return View();
}
}
catch
{
ViewBag.message = "Header method Failed";
}
return View();
}
Now I wonder if there are better ways of doing this. Someone enlighten me.
So I'm trying to setup ajax-exchange between a JavaScript frontend and ASP.NET backend. I've stumbled upon this example from w3schools:
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "demo_get2.asp?fname=Henry&lname=Ford", true);
xhttp.send();
}
However, it's unclear to me how to handle this request on server side. What should my demo_get2.asp look like to process this request?
In Asp.NET, you can do this by clearing all the headers and response built so far by the framework then adding your custom data and header and flushing out the response without any other additional framework methods to be called (like, prerender, render methods) as below.
protected void Page_Load(object sender, EventArgs e)
{
// Add logic here to populate any data to send
Response.Clear();
Response.ClearHeaders();
Response.AddHeader("Content-Type", "text/plain"); // This can be your data type
Response.Write("This is plain text"); // This can be your data
Response.Flush();
Response.End();
}
I want to transfer some json data to server by using JavaScript xmlHttpRequest.
For simplify, assume that I've got a json like {"name":"John","country":"English"}, then I'm going to POST it back to the server. I use Request["name"] to get the request data but always result in NullOrEmpty, which means I cannot get inside #1. Thus leading to that #2 shows the entire HTML Document.
Here's my code:
**JavaScript:**
function AjaxTest()
{
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (xhttp.readyState == 4 && xhttp.status == 200) {
alert(xhttp.responseText);//**#2.**
}
};
xhttp.open("POST", "WebForm.aspx", true);
xhttp.setRequestHeader("Content-type", "application/json;charset=UTF-8");
var json = '{"name":"John","country":"English"}';
xhttp.send(json);
}
**Codebehind:**
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
string name = Request["name"];
string country = Request["country"];
if(!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(country))
{
//**#1.** I cannot get here.
}
}
}
I do know that I've done something wrong, but how can I get the reques data? As a newbie to Ajax, any help will be greatly appreciated.
Thanks in advance.