I am trying to debug a particular connection that responds with a Unauthorized (401). In Restlet this causes Respresentation.get() to throw an error.
What I want to do is get the response body as this particular api gives you greater error information in the body.
Any suggestions?
Thanks,
Luke
I would be reluctant to reccomend it for production but certainly for debugging you can override handleInbound in ClientResource to change the conditions under which an error is thrown. Restlet will then return the body, in the usual way.
ClientResource clientResource = new ClientResource("http://your.url") {
#Override
public Representation handleInbound(Response response) {
Representation result = null;
if (response.getRequest().isSynchronous()) {
if (response.getStatus().isError()
&& !Status.CLIENT_ERROR_UNAUTHORIZED.equals(response.getStatus())) {
doError(response.getStatus());
} else {
result = (response == null) ? null : response.getEntity();
}
}
return result;
}
};
Representation response = clientResource.get();
System.out.println(response.getText());
Related
ServiceStack doesn't populate the original response in the WebServiceException's responseDTO property.
I'm running the code below which should always return a 404 response code with the ResponseStatus property of the TestResponse populated with "Some bad request" but it also seems like should return the original good response with it's output property populated from the request's input property. However I get null when I look at the WebServiceException responseDTO
public TestResponse Post(Test request)
{
var response = new TestResponse() { Output = request.Input };
throw new HttpError(response, (int)HttpStatusCode.BadRequest, "Some bad request");
}
public TestResponse Get(Test request)
{
try
{
using (var client = new JsonServiceClient("http://localhost:5000"))
{
var response = client.Post(request);
return response;
}
}
catch (WebServiceException ex)
{
throw;
}
}
In general I was expecting that the responseDTO property in the WebServiceException will contain the endpoint's DTO as long as it's passed in when throwing the HttpError but that doesn't seem to be the case. I see only default values and nulls for each property in the responseDTO.
When an Exception is thrown only the ResponseStatus is preserved, you can add any additional info to its Meta dictionary.
Alternatively you can return a failed HTTP Response:
public TestResponse Post(Test request)
{
var response = new TestResponse() { Output = request.Input };
base.Response.StatusCode = (int)HttpStatusCode.BadRequest;
return response;
}
I'm getting a BadRequestException when using Jersey 2 and I'd like to get the URL that was used in the request and print it in the logs when the exception is caught.
Is there a property/method combination on the BadRequestException object that will return the URL? I don't see it in the JavaDocs, but it could have a name unrelated to "URL".
You can't get URI from BadRequestException. But you can get it from WebTarget you invoked the request on:
WebTarget target = ClientBuilder.newClient().target("http://localhost");
try {
String result = target.request().get(String.class);
} catch (BadRequestException bre) {
// get the URI
target.getUri();
}
If you don't want to use try-catch block:
Response response = target.request().get();
if (response.getStatus() == 200) {
// OK
} else {
// Handle other state.
}
I am having trouble returning the correct HTTP error code for a "not found" in my WCF Web API code. Here is my api method ...
[WebInvoke(Method = "GET", UriTemplate = "{id}")]
[RequireAuthorisation]
public Customer GetCustomer(int id)
{
var customer = Repository.Find(id);
if (customer == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return customer;
}
I also have a logging handler ...
protected override bool OnTryProvideResponse(Exception exception, ref HttpResponseMessage message)
{
if (exception != null)
{
var msg = "Request failed.";
_logger.Error(exception, msg);
}
message = new HttpResponseMessage
{
StatusCode = HttpStatusCode.InternalServerError
};
return true;
}
What is happening is I am getting the following exception ...
HttpResponseException
"The response message returned by the Response property of this exception should be immediately returned to the client. No further handling of the request message is required."
... which my logging handler picks up and changes the response status code to a 500.
So, based on reading a few blog posts and answers on SO, I changed to this ...
if (customer == null)
{
WebOperationContext.Current.OutgoingResponse.SetStatusAsNotFound();
return null;
}
... but this now give me a 200. Which is clearly wrong.
So, what is the right way to do this? It seems as if the throwing of the HttpResponseException doesn't work and the code after gets executed.
The code snippet for your error handler is always changing the response message to 500 no matter what as you are explicitly setting the status always to 500.
It sounds like what you are trying to do is return a 500 ONLY if it is an application error. If that is the case you should check if the error exception is an HttpResponseException and just return rather than overriding.
As to WebOperationContext, don't use it at all with Web Api as it is basically no-op.
Hope this helps
Glenn
I'm trying to return the 'Allow' entity header within the response message and I keep getting the following message:
{"The header cannot be added. Make sure to add request headers to HttpRequestMessage, response headers to HttpResponseMessage, and content headers to HttpContent objects."}
Here's the code snippet:
[WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
public HttpResponseMessage<Order> DeleteOrder(int id)
{
HttpResponseMessage<Order> response = null;
try
{
if (id <= 0)
{
response = new HttpResponseMessage<Order>(HttpStatusCode.BadRequest);
}
else
{
// For brevity, I'm assuming that order - 123456 was already served and logged. Hence it cannot
// be deleted. Order 12345, however, can be deleted.
// Note: The code doesn't actual delete anything. This is just a demonstration of
// the DELETE verb
if (id == 12345)
{
return new HttpResponseMessage<Order>(HttpStatusCode.NoContent);
}
if (id == 123456)
{
response = new HttpResponseMessage<Order>(HttpStatusCode.MethodNotAllowed);
response.Headers.AddWithoutValidation("Allow", "PUT");
}
// return '404 - Not Found' status code
response = new HttpResponseMessage<Order>(HttpStatusCode.NotFound);
}
return response;
}
catch (Exception ex)
{
return response = new HttpResponseMessage<Order>(HttpStatusCode.InternalServerError);
}
}
Any advice would be very helpful.
Thanks,
dorman
Try response.Content.Headers instead.
I'm trying to create a HEAD response with restlet. Unfortunatly there is ony a #Get annotation, but the restlet author states, that you have to use a #Get, and then compare the Method.
As the documentation/specification says, there can be no body, but only a message header.
Now how to create a message header that will be send to the server, because the following code does not work, it sends this headers: HTTP/1.1 204 No Content, Content-Length: 0
protected void addResponseHeader(String name, String value) {
Form responseHeaders = (Form)getResponse().getAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS);
if (responseHeaders == null) {
responseHeaders = new Form();
getResponse().getAttributes().put(HeaderConstants.ATTRIBUTE_HEADERS, responseHeaders);
}
responseHeaders.add(new Parameter(name, value));
}
The concrete code on server-side:
#Get
public void execute() {
if (Method.HEAD.equals(getMethod())) {
//optional: getResponse().getEntity().setMediaType(MediaType.TEXT_PLAIN);
getResponse().setStatus(Status.SUCCESS_OK, "hello head");
addResponseHeader("X-my-header", "value");
}
}
The client code:
#Test
public void head() {
Request request = new Request(Method.HEAD, url);
Response response = query(request);
assertEquals(Status.SUCCESS_OK, response.getStatus());
Form form = (Form)response.getAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS);
assertEquals("value", form.getFirstValue("X-my-value")); // does fail because it is null
}
You just need to implement #Get for real : should work with a HTTP GET fine first. Then if you issue a HTTP HEAD, it will be handled automatically by the framework, nothing else to do on your side. Just focus on getting GET implemented correctly.