Callout Mystery
The tale of the GET that turned into a POST.
Basics:
HTTP (Hypertext Transfer Protocol) enables communications between clients and servers, or in other words - let computers with or without screens (servers being computers without a screen) talk to eachother.
The usual client would be the browser you are using to read this text, and the screenless computer (or network of computers) that provided this text is utilized by medium, the company.
A callout is the way in which the client is requesting info from the server. Like, hey dude. Yes, you at the address 127.0. 0.1 (that’s our home address 😉). Yes, hi there, anyone home?! Then the server would answer like, yeah, we might be home, whoes asking?! And the client would be all cool about this and provide the details. The server will then change the attitude and be like, ok, you cool. What you want? And the client will make the specific request, like - give me all the words for this article. The server will be all cool about it, send the text in the response, and the page will render. If everything works out correctly, the whole thing will be under a second, or two.
The specifics:
Salesforce provides several built-in classes to work with HTTP services and create HTTP requests like GET, POST, PUT, and DELETE.
HTTP class
HttpRequest Class
HttpResponse Class
public class HttpCalloutSample {
public String getCalloutResponseContents(String url) {
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint(url);
req.setMethod('GET');
HttpResponse res = h.send(req);
return res.getBody();
}
}
The mystery started with this Salesforce Log entry:
CALLOUT_REQUEST | System.HttpRequest[Endpoint= https://xxxx.xxxx.xxxx, Method=GET]CALLOUT_RESPONSE | System.HttpResponse[Status=Method Not Allowed, StatusCode=405]
Every Http Response has a specific StatusCode that classify the response, making everyones’ life easier. The list of codes includes 5 different catagories:
- Informational Response: the request was received, continuing process
- Successful: the request was successfully received, understood & accepted
- Redirection: further action needed in order to complete the request
- Client Error: the request contains bad syntax or cannot be fulfilled
- Server Error: the server failed to fulfil an apparently valid request
The 405 StatusCode falls under the Client Error category, and let us know that this error has originated on our end (the client) as the ones making the request.
405 Method Not Allowed
A request method is not supported for the requested resource; for example, a GET request on a form that requires data to be presented via POST, or a PUT request on a read-only resource.
And this is the mystery right there.
The resolution:
The Method in the Method Not Allowed error referrs to one of the 4 options: GET, POST, PUT, and DELETE. Basically the server (endpoint is the server address in a way), letting you know that it is expecting a specific method, and you are using a different one. In our mystery, the server expected a GET, we think we used a GET, but actually, we send a POST. So what happened?
The answer in this case was relativly simple. Can you spot it?
HttpRequest req = new HttpRequest();
req.setEndpoint(url);
req.setMethod('GET');
req.setBody();
req.setHeader('Content-Type', 'application/json');
req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
It was all the fault of the line
req.setBody();
Even though the method param is null, once we set a body to the request, the request method will implicitly change to a POST. Nope, you won’t get a linter alert either.
Mystery solved. Faster than locating these errors. Hopefully.