Is there a way to log the http request and response?
Let's assume the below request
Connection.Response res = Jsoup.connect("LOGIN_URL_HERE")
.data("user", "USER", "pass", "PASS")
.method(Connection.Method.POST)
.execute();
How can I log the http request and response? Please mind that I want the HTTP and not just the HTML that will be parsed.
By default jsoup uses a implementation of java.net.HttpURLConnection So I suppose you need to turn on logging for that implementation (probably: sun.net.www.protocol.http.HttpURLConnection) or for java.net.
There is a system property that will enable logging for java net utils
-Djavax.net.debug=all
As Jsoup lacks logging (version I'm using: 1.12.1) and using the -Djavax.net.debug=all JVM argument logs are too verbose, the best way I found is to decorate the HttpConnection class, so one can customize what is logged. To achive this, the execute method call needs to be surrounded by logging the properties of the Connection.Request and Connection.Response.
Sample implementation using SLF4J:
import org.jsoup.Connection;
import org.jsoup.helper.HttpConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class DiagnosticConnection extends HttpConnection {
static final Logger LOG = LoggerFactory.getLogger(DiagnosticConnection.class);
#Override
public Connection.Response execute() throws IOException {
log(this.request());
Connection.Response response = super.execute();
log(response);
return response;
}
public static Connection connect(String url) {
Connection connection = new DiagnosticConnection();
connection.url(url);
return connection;
}
private static void log(Connection.Request request) {
LOG.info("========================================");
LOG.info("[url] {}", request.url());
LOG.info("== REQUEST ==");
logBase(request);
LOG.info("[method] {}", request.method());
LOG.info("[data] {}", request.data());
LOG.info("[request body] {}", request.requestBody());
}
private static void log(Connection.Response response) {
LOG.info("== RESPONSE ==");
logBase(response);
LOG.info("[code] {}", response.statusCode());
LOG.info("[status msg] {}", response.statusMessage());
LOG.info("[body] {}", response.body());
LOG.info("========================================");
}
private static void logBase(Connection.Base<?> base) {
LOG.info("[headers] {}", base.headers());
LOG.info("[cookies] {}", base.cookies());
}
}
When using the decorator, instead of Jsoup.connect(<URL>) you should use DiagnosticConnection.connect(<URL>)
Based on Gergely Toth response, I have created my own LoggerHttpConnection and I'm working with that.
import android.util.Log
import org.jsoup.Connection
import org.jsoup.helper.HttpConnection
import org.jsoup.nodes.Document
import org.jsoup.parser.Parser
import java.io.InputStream
import java.net.Proxy
import java.net.URL
import javax.net.ssl.SSLSocketFactory
class LoggerHttpConnection private constructor(
private val delegate: HttpConnection,
private val saveFile: Boolean
) : Connection {
private val tag = "LoggerHttpConnection"
companion object {
fun connect(url: String, saveFile: Boolean = false): LoggerHttpConnection {
return LoggerHttpConnection(
HttpConnection.connect(url) as HttpConnection,
saveFile
)
}
}
private fun log(request: Connection.Request): String {
Log.i(tag, "========================================")
var line = "[url] ${request.url()}"
var log = "$line\n\n== REQUEST ==\n"
Log.i(tag, line)
Log.i(tag, "== REQUEST ==")
log += logBase(request)
line = "[method] ${request.method()}"
log += "$line\n"
Log.i(tag, line)
for (data in request.data()) {
line = "[data] ${data.key()}=${data.value()}"
log += "$line\n"
Log.i(tag, line)
}
line = "[request body] ${request.requestBody()}"
log += "$line\n"
Log.i(tag, line)
return log
}
private fun log(response: Connection.Response): String {
var line = ""
var log = "\n== RESPONSE ==\n"
Log.i(tag, "== RESPONSE ==")
log += logBase(response)
line = "[code] ${response.statusCode()}"
log += "$line\n"
Log.i(tag, line)
line = "[status msg] ${response.statusMessage()}"
log += "$line\n"
Log.i(tag, line)
line = "[body] ${response.body()}"
log += "$line\n"
Log.i(tag, line)
Log.i(tag, "========================================")
return log
}
private fun logBase(base: Connection.Base<*>): String {
var line = ""
var log = ""
for (header in base.headers()) {
line = "[header] ${header.key}=${header.value}"
log += "$line\n"
Log.i(tag, line)
}
for (cookie in base.cookies()) {
line = "[cookie] ${cookie.key}: ${cookie.value}"
log += "$line\n"
Log.i(tag, line)
}
return log
}
override fun execute(): Connection.Response {
var logs = log(request())
val response = delegate.execute()
logs += log(response)
if (saveFile)
logs.saveToFile("request_log") //do something to save your log in a file if its necesary
return response
}
override fun ignoreContentType(ignoreContentType: Boolean): Connection {
delegate.ignoreContentType(ignoreContentType)
return this
}
override fun postDataCharset(charset: String?): Connection {
delegate.postDataCharset(charset)
return this
}
override fun get(): Document {
return delegate.get()
}
override fun post(): Document {
return delegate.post()
}
/** Continue implementing necessary methods for Connection */
}
Now just declare your request using LoggerHttpConnection instead Jsoup and everything will work
Connection.Response res = LoggerHttpConnection.connect("LOGIN_URL_HERE")
.data("user", "USER", "pass", "PASS")
.method(Connection.Method.POST)
.execute();
Related
I am developing android application in which i send data to server using cronet now i want to send data to server in json object but not know how to send in object?
Following is my snippet code for GET method (WORKING).
Can anyone share how to use POST Method in android cronet ?
Dependencies
implementation 'org.chromium.net:cronet-embedded:71.3578.98'
MainActivity
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import org.chromium.net.CronetEngine
import java.util.concurrent.Executors
class MainActivity : AppCompatActivity() {
companion object {
// Web page url
private const val JSON_PLACEHOLDER_API_URL = "https://jsonplaceholder.typicode.com/todos/1"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Build a Cronet engine
val cronetEngine =
CronetEngine.Builder(this)
.enableBrotli(true)
.build()
// Build the request
val request =
cronetEngine.newUrlRequestBuilder(
JSON_PLACEHOLDER_API_URL,
RequestCallback(),
Executors.newSingleThreadExecutor()
).build()
// Start the request
request.start()
}
}
RequestCallback
import android.util.Log
import org.chromium.net.CronetException
import org.chromium.net.UrlRequest
import org.chromium.net.UrlResponseInfo
import java.nio.ByteBuffer
import java.nio.charset.Charset
/**
* Different methods are invoked for different response status
*/
class RequestCallback : UrlRequest.Callback() {
companion object {
// Log cat tag
private val TAG = RequestCallback::class.java.simpleName
}
override fun onResponseStarted(request: UrlRequest?, info: UrlResponseInfo?) {
Log.i(TAG, "Response Started")
val statusCode = info?.httpStatusCode
Log.i(TAG, "Status Code $statusCode")
if (statusCode == 200) {
// Read the buffer
request?.read(ByteBuffer.allocateDirect(32 * 1024))
}
}
override fun onReadCompleted(request: UrlRequest?, info: UrlResponseInfo?, byteBuffer: ByteBuffer?) {
Log.i(TAG, "Response Completed")
// Flip the buffer
byteBuffer?.flip()
// Convert the byte buffer to a string
byteBuffer?.let {
val byteArray = ByteArray(it.remaining())
it.get(byteArray)
String(byteArray, Charset.forName("UTF-8"))
}.apply {
Log.d(TAG, "Response: $this")
}
// Clear the buffer
byteBuffer?.clear()
// Read the buffer
request?.read(byteBuffer)
}
override fun onFailed(request: UrlRequest?, info: UrlResponseInfo?, error: CronetException?) {
Log.e(TAG, "Response Failed: ${error?.message}")
}
override fun onSucceeded(request: UrlRequest?, info: UrlResponseInfo?) {
Log.i(TAG, "Response Succeeded")
}
override fun onRedirectReceived(request: UrlRequest?, info: UrlResponseInfo?, newLocationUrl: String?) {
Log.i(TAG, "Response Redirect to $newLocationUrl")
request?.followRedirect()
}
override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) {
super.onCanceled(request, info)
Log.i(TAG, "Response cancelled")
}
}
Output
Response: {
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
Example:
val myBuilder = CronetEngine.Builder(context)
// Enable caching of HTTP data and
// other information like QUIC server information, HTTP/2 protocol and QUIC protocol.
val cronetEngine: CronetEngine = myBuilder
.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_IN_MEMORY, 100 * 1024.toLong())
.enableHttp2(true)
.enableQuic(true)
.build()
val executor: Executor = Executors.newSingleThreadExecutor()
val requestBuilder = cronetEngine.newUrlRequestBuilder(
"FULL-URL",
MyUrlRequestCallback(),
executor
)
// Content-Type is required, removing it will cause Exception
requestBuilder.addHeader("Content-Type","application/json; charset=UTF-8")
requestBuilder.setHttpMethod("POST")
val myUploadDataProvider = MyUploadDataProvider()
requestBuilder.setUploadDataProvider(myUploadDataProvider,executor)
val request: UrlRequest = requestBuilder.build()
request.start()
MyUploadDataProvider Class:
import android.util.Log
import org.chromium.net.UploadDataProvider
import org.chromium.net.UploadDataSink
import java.lang.Exception
import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets
private const val TAG = "MyUploadDataProvider"
//TODO replace username and passowrd "_user & _pass"
var string: String ="{\"username\":\"_user\",\"password\":\"_pass\"}"
val charset = StandardCharsets.UTF_8
class MyUploadDataProvider() : UploadDataProvider() {
override fun getLength(): Long {
val size:Long = string.length.toLong()
Log.e(TAG,"Length = "+size)
return size
}
override fun rewind(uploadDataSink: UploadDataSink?) {
Log.e(TAG,"REWIND IS CALLED")
uploadDataSink!!.onRewindSucceeded()
}
override fun read(uploadDataSink: UploadDataSink?, byteBuffer: ByteBuffer?) {
Log.e(TAG,"READ IS CALLED")
byteBuffer!!.put(string.toByteArray(charset))
//byteBuffer.rewind()
//For chunked uploads, true if this is the final read. It must be false for non-chunked uploads.
uploadDataSink!!.onReadSucceeded(false)
}
}
I want to use access token to get userinfo with a java open-id connect library the same as nodejs.
I use npm-openid-client to get the userInfo and it works very well in nodejs
/**
** client_id and client_secret can be empty now
*/
const { Issuer } = require('openid-client');
const end_point = 'xxx'
const access_token = 'xxx'
Issuer.discover(end_point).then(function (issuer) {
const client = new issuer.Client({
client_id: 'xx',
client_secret: 'xx',
});
client.userinfo(access_token).then(function (userinfo) {
console.log('userinfo %j', userinfo);
});
});
I google java open-id library and find some library from openid.net
and finally I use connect2id
I follow the link openid-connect/userinfo and write some code below:
import java.io.*;
import java.net.*;
import com.nimbusds.oauth2.sdk.http.*;
import com.nimbusds.oauth2.sdk.token.*;
import com.nimbusds.openid.connect.sdk.claims.*;
class Test {
public static void main (String[] args) throws Exception{
String uriStr = "";
String tokenStr = "";
URI userInfoEndpoint = new URI(uriStr);
BearerAccessToken token = new BearerAccessToken(tokenStr);
// Make the request
HTTPResponse httpResponse = new UserInfoRequest(userInfoEndpoint, token)
.toHTTPRequest()
.send();
// Parse the response
UserInfoResponse userInfoResponse = UserInfoResponse.parse(httpResponse);
if (! userInfoResponse.indicatesSuccess()) {
// The request failed, e.g. due to invalid or expired token
System.out.println(userInfoResponse.toErrorResponse().getErrorObject().getCode());
System.out.println(userInfoResponse.toErrorResponse().getErrorObject().getDescription());
return;
}
// Extract the claims
UserInfo userInfo = userInfoResponse.toSuccessResponse().getUserInfo();
System.out.println("Subject: " + userInfo.getSubject());
System.out.println("Email: " + userInfo.getEmailAddress());
System.out.println("Name: " + userInfo.getName());
}
}
the result is that httpResponse return 404 not found. how can I fix it and get the userInfo ?
I have a resteasy webservice on a wildfly 10 on the same machine as my angular client.
Get request works
Put and delete are called 2 times as I understood is because a preflight request is done. A curl -X DELETE http://localhost:8080/resteasyWebServices-1.0-SNAPSHOT/company/57 -i works well on it without doing requests twice. At the contrary, when called with angular client, the restWebService is called twice!
I tried to add a corsFilter but more than helping me being able to do get requests it didn't help me to solve my problem
package com.solarity.app; // {{ groupId}}.app
import com.solarity.rest.CompanyRestService;
import com.solarity.rest.PersonRestService;
import org.jboss.resteasy.plugins.interceptors.CorsFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
#ApplicationPath("/")
public class InitApplication extends Application {
/**
*
*/
Set<Object> singletons;
HashSet<Class<?>> webServiceClasses;
public InitApplication() {
super();
webServiceClasses = new HashSet<>();
webServiceClasses.add(PersonRestService.class);
webServiceClasses.add(CompanyRestService.class);
singletons = new LinkedHashSet<>();
singletons.add(this.getCorsFilter());
}
#Override
public Set<Class<?>> getClasses() {
return webServiceClasses;
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
private CorsFilter getCorsFilter() {
CorsFilter result = new CorsFilter();
result.getAllowedOrigins().add("http://localhost:4200");
return result;
}
}
I tried to implement an options method into my webservice without success...
package com.solarity.rest; // Note your package will be {{ groupId }}.rest
import com.solarity.entities.CompanyEntity;
import com.solarity.entities.PersonEntity;
import com.solarity.service.CompanyService;
import com.solarity.service.PersonService;
import com.solarity.util.ResponseUtil;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
*
*
*/
#Path("/company")
public class CompanyRestService {
protected Logger logger = LoggerFactory.getLogger(getClass());
private CompanyService companyService = new CompanyService();
#GET // This annotation indicates GET request
#Path("/")
#Produces(MediaType.APPLICATION_JSON)
public Response getAll() {
Object response = null;
String errMsg = null;
int responseStatus = -1;
try {
this.logger.debug("companyServcfindAll----------------debug");
this.logger.warn("companyServcfindAll----------------WARN");
response = companyService.findAll();
} catch (Exception e) {
errMsg = "Error getting all persons";
logger.error(errMsg, e);
}
return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.GET);
}
/**
* curl -X DELETE http://localhost:8080/resteasyWebServices-1.0-SNAPSHOT/company/57 -i
*
* #param id
* #return
*/
#DELETE
#Path("/{param}")
public Response delete(#PathParam("param") Integer id){
Object response = null;
String errMsg = null;
int responseStatus = -1;
try {
logger.debug("Deleting entity", id);
companyService.delete(id);
responseStatus = HttpStatus.SC_OK;
} catch (Exception e) {
errMsg = "Error Deleting Entity:" + id;
logger.error(errMsg, e);
response = errMsg;
responseStatus = HttpStatus.SC_METHOD_FAILURE;
}
return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.DELETE);
}
/**
* Not working
* #return
*/
#OPTIONS
#Path("{path : .*}")
public Response options() {
return Response.ok("")
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
.header("Access-Control-Max-Age", "1209600")
.build();
}
}//end Class
Here is my ResponseUtils class
package com.solarity.util;
import org.apache.http.HttpStatus;
import javax.ws.rs.core.Response;
public class ResponseUtil {
/**
*
Built to counter a Angular cross-reference problem
Adapted for Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/dlssResteasy1-1.0-SNAPSHOT/person/getPersonsAsJSON. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
source answer https://stackoverflow.com/questions/23450494/how-to-enable-cross-domain-requests-on-jax-rs-web-services?answertab=votes#tab-top
More Documentation about CORS on https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
* #param param the object to send if errorMsg is null
* #param errorMsg if not null sends an error code with error Message
* #param responseStatus response status which can be found from HttpStatus.* (if <= 0 will be taken from errorMsg, or ok)
* #return an altered response which is customized
*/
public static Response getAlteredResponse( Object param, String errorMsg, int responseStatus, String httpMethod ) {
Response result = null;
int rStatus = responseStatus;
if (errorMsg != null && responseStatus <= 0) {
rStatus = HttpStatus.SC_UNPROCESSABLE_ENTITY;
} else if (errorMsg == null && responseStatus <= 0){
rStatus = HttpStatus.SC_OK;
}
if ( errorMsg == null ) {
result = Response
.status(rStatus)
.entity(param)
.build();
}else{
result = Response.status(rStatus)
.entity(errorMsg)
.build();
}
return result;
}
}
Here is the result of debug into FF
Observe the OPTIONS request and response and be certain that the OPTION response coming from the server has the correct information. It tells the client what the server is accepting
Observe later the real request PUT GET POST , etc going to the server .Does it has all the headers that you want ?
You do not need to create and OPTIONS route .See here the RFC https://www.w3.org/TR/cors/
Add to this thread the copy of the OPTIONS request and response ( not the one you created but the one from the package your are using, if you are not using a package , look for one) , to see what is wrong with the configuration.
Add also the next POST,GET,PUT, etc. both the request and response
First of all there is a documentation about CORS I HAD TO READ to understand, I couldn't avoid that as I hoped...
Two calls from Angular
Part of the answer of my problem was in fact two calls from Angular.
I didn't understand that everytime a call to subscribe on an httpclient.put() is done a call is done!
HttpClient Documentation
Calling the subscribe() method executes the observable, which is what
initiates the DELETE request.
So What I did was:
Call methodResult = httpclient.put('someUrl', someData, someHeader).subscribe({ data => { console.log('added') });
On the caller of this method call again with abovePutMethod.subscribe( data => { doSomeThingWithComponentRefresh })
So doing only ONE call to subscribe solved my twice call problem
For the rest of the CORS Protocol
Angular Client
//UrlHelper
public static putHttpRequestOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
};
//Function call somewhere
const result = this.httpClient.put(url, jsonStringValues, UrlHelper.putHttpRequestOptions);
Java Resteasy server
// InitApplication extends Application
public InitApplication() {
super();
webServiceClasses = new HashSet<>();
webServiceClasses.add(PersonRestService.class);
webServiceClasses.add(CompanyRestService.class);
singletons = new LinkedHashSet<>();
singletons.add(this.getCorsFilter());
}
private CorsFilter getCorsFilter() {
CorsFilter result = new CorsFilter();
result.getAllowedOrigins().add("*");
result.setAllowedMethods("OPTIONS, GET, POST, DELETE, PUT, PATCH");
result.setCorsMaxAge(86400);//Max in FF 86400=24h https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
//
return result;
}
// RestWebService
#PUT
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
public Response put(CompanyEntity entity ){
Object response = null;
String errMsg = null;
int responseStatus = -1;
try {
logger.debug("Received entity", entity);
companyService.persist(entity);
responseStatus = HttpStatus.SC_CREATED;
} catch (Exception e) {
errMsg = "Error adding Entity:" + entity;
logger.error(errMsg, e);
response = errMsg;
responseStatus = HttpStatus.SC_METHOD_FAILURE;
}
return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.PUT);
}
// Called on result of all RestWebServices (I'm sure there are better/best practices, feel free to comment me this section)
/**
* #param param the object to send if errorMsg is null
* #param errorMsg if not null sends an error code with error Message
* #param responseStatus response status which can be found from HttpStatus.* (if <= 0 will be taken from errorMsg, or ok)
* #return an altered response which is customized
*/
public static Response getAlteredResponse( Object param, String errorMsg, int responseStatus, String httpMethod ) {
Response result = null;
int rStatus = responseStatus;
if (errorMsg != null && responseStatus <= 0) {
rStatus = HttpStatus.SC_UNPROCESSABLE_ENTITY;
} else if (errorMsg == null && responseStatus <= 0){
rStatus = HttpStatus.SC_OK;
}
String accessControlAllowMethods = "GET, POST, PUT, DELETE, OPTIONS, HEAD";
if ( errorMsg == null ) {
result = Response
.status(rStatus)
.header("Access-Control-Allow-Origin", "*") //TODO: fix permission here!
.header("Access-Control-Allow-Methods", accessControlAllowMethods)
.header("Access-Control-Max-Age", "1728000")
.entity(param)
.build();
}else{
result = Response.status(rStatus)
.header("Access-Control-Allow-Origin", "*") //TODO: fix permission here!
.header("Access-Control-Allow-Methods", accessControlAllowMethods)
.header("Access-Control-Max-Age", "1728000")
.entity(errorMsg)
.build();
}
return result;
}
You can see the traffic with Chrome DevTools in the Network tab
In my Jax-Rs(Jersey + Jetty) application, I've added some custom headers to the response so that I can use those at the client side. I'm using ResponseBuilder to achieve this.
#Provider
public class CustomExceptionMapper implements ExceptionMapper<CustomException> {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomExceptionMapper.class);
#Context
private HttpHeaders headers;
#Override
public Response toResponse(CustomException exception) {
String errorKey = null;
String errorArgs[] = null;
// log stack trace
LOGGER.error("An error occurred during the operation.", exception);
if (exception instanceof MetadataServerException) {
errorKey = ExceptionMapperUtil.checkForDBException(exception.getCause());
if (errorKey != null) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(MessageSourceUtils.getMessage(errorKey, errorArgs, ExceptionMapperUtil.getLocale(headers))).type(MediaType.TEXT_PLAIN).build();
}
}
if(ErrorCodes.INTERNAL_SERVER_ERROR.equals(exception.getMessageKey()) &&
(exception.getMessageArguments() == null || exception.getMessageArguments().length==0) ){
exception.setMessageArguments(new Object[]{"while executing the operation"});
}
// prepare response to be sent to client
return Response.status(ResponseCodeMapper.mapToStatusCode(exception)).
entity(exception.getMessage(ExceptionMapperUtil.getLocale(headers))).
type(MediaType.TEXT_PLAIN).header("errorCode", exception.getMessageKey()).
build();
}
}
And also, I've confirmed that that the response object is getting built properly. However, for some reason, the returned response doesn't contain my custom header. Any clues as to to what is going wrong ?
I'm trying to make Cross Site Request using GWT Request builder, which i couldn't get it to work yet. As you can see, this is much of a Sample GWT Project and i have gone through https://developers.google.com/web-toolkit/doc/latest/tutorial/Xsite . But still i'm missing something.
I'm Posting the code here. What am i missing ..?
package com.gwt.reqbuilder.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Window;
public class GWTRequestBuilder implements EntryPoint
{
private static final String JSON_URL = "http://localhost:8000/?q=ABC&callback=callback125";
public void onModuleLoad()
{
GWTPOSTHTTP();
}
public void GWTPOSTHTTP()
{
String postUrl="http://localhost:8000";
String requestData="q=ABC&callback=callback125";
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, postUrl);
try {
builder.sendRequest(requestData.toString(), new RequestCallback()
{
public void onError(Request request, Throwable e)
{
Window.alert(e.getMessage());
}
public void onResponseReceived(Request request, Response response)
{
if (200 == response.getStatusCode())
{
Window.alert(response.getText());
} else {
Window.alert("Received HTTP status code other than 200 : "+ response.getStatusText());
}
}
});
} catch (RequestException e) {
// Couldn't connect to server
Window.alert(e.getMessage());
}
}
}
Actually we can make Cross Site Requests from GWT RequestBuilder if we can set in Servlet Response Header
Response.setHeader("Access-Control-Allow-Origin","http://myhttpserver");
It's working Cool , if anyone need the GWT Project and Python Servlet, please do let me know, i can upload the files.
GWT Client Code : https://github.com/manikandaraj/MLabs/tree/master/GWT/GWTClient
You've missed to finish reading the tutorial.
Direct quote from the tutorial :
The RequestBuilder code is replaced by a call to the getJson method. So you no longer need the following code in the refreshWatchList method:
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
try {
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
displayError("Couldn't retrieve JSON");
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
updateTable(asArrayOfStockData(response.getText()));
} else {
displayError("Couldn't retrieve JSON (" + response.getStatusText()
+ ")");
}
}
});
} catch (RequestException e) {
displayError("Couldn't retrieve JSON");
}
Which is broadly what you've got, and should be replaced by a JSNI function given in the tutorial a few lines below :
/**
* Make call to remote server.
*/
public native static void getJson(int requestId, String url,
StockWatcher handler) /*-{
var callback = "callback" + requestId;
// [1] Create a script element.
var script = document.createElement("script");
script.setAttribute("src", url+callback);
script.setAttribute("type", "text/javascript");
// [2] Define the callback function on the window object.
window[callback] = function(jsonObj) {
// [3]
handler.#com.google.gwt.sample.stockwatcher.client.StockWatcher::handleJsonResponse(Lcom/google/gwt/core/client/JavaScriptObject;)(jsonObj);
window[callback + "done"] = true;
}
...