In my Apex code, I am trying to download a remote csv file to process in-memory. Unfortunately, I am getting a System.CalloutException: Premature EOF error when I try to get the file. I am able to connect to the server with the file (I can see the error messages returned when the file is not ready for download) so the connection details are likely not the problem.
private static void processURL(String url, UserHelper__c helper){
String username = 'login';
String password = 'password';
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();
req.setEndpoint(url);
Blob headerValue = Blob.valueOf(username + ':' + password);
String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue);
req.setHeader('Authorization', authorizationHeader);
req.setMethod('GET');
try {
System.debug('processURL Send request: '+req);
res = http.send(req); //Premature EOF hits here.
System.debug('processURL successful');
} catch(System.CalloutException e) {
System.debug('processURL error: '+ e);
}
...
}
This was caused by the server sending its response in a buffered manner. It seems that the SalesForce Apex code cannot handle a buffered response. I don't have all the details on what happened on the server-side so I cannot give more details than that.
Related
I am trying to call the Microsoft Graph API to create a domain. Unfortunately when I go to make the call, I receive an error stating that the "JSON Payload is empty".
Here is the call I am making:
GraphServiceClient _graphServiceClient =
new GraphServiceClient(new GraphAuthenticationHelper(NetOrgDomain));
HttpRequestMessage httpRequestMessage =
new HttpRequestMessage(httpMethod, requestUri);
string content = "{\"id\": \"sampleDomainAdd.info\"}";
var json = JsonConvert.SerializeObject(content);
var jsonContent = new StringContent(json, Encoding.UTF8, "application/json");
httpRequestMessage.Content = jsonContent;
HttpResponseMessage response =
await _graphServiceClient.HttpProvider.SendAsync(httpRequestMessage);
You've got an mix of Graph SDK and direct HTTP calls going on here. When using the Microsoft Graph .NET Client Library, you should be using the objects it provides rather than attempting to roll your own.
It also greatly simplifies your code:
var domain = await graphClient.Domains.Request().AddAsync(new Domain
{
Id = "sampleDomainAdd.info"
});
As an aside, the error you're getting currently is due to you're sending the data without the content-type being set to application/json in your HTTP request.
While trying to setup oauth in the org, getting status code 302.
Below is the code snippet.
String AUTH_URL = 'https://login.salesforce.com/services/oauth2/authorize';
String redirect_uri = 'https://login.salesforce.com/services/oauth2/success';
String response_type = 'token';
String client_id = 'xxxxxxxxxxxxxx.xxxxxxxxx';
authURL = AUTH_URL +
'?response_type=' + response_type +
'&client_id=' + client_id +
'&redirect_uri=' + redirect_uri;
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();
req.setMethod('GET');
req.setEndpoint(authUrl);
res = http.send(req);
//RESULT:
res.getStatusCode() = 302
res.getStatus() = Found
I am expecting to receive access Token and refresh token in response's body but it is empty.
Please suggest if I am missing out on something.
Thanks in advance.
the authorize endpoint is for a browser based interactive login, not a programatic login. If you want a pure programatic method, then you should checkout the username/password oauth flow that you can use via the /services/oauth2/token endpoint.
I am trying to create httpwebrequest to one url (REST API) where i am writing stream to target api server. But before writing stream, in my request object : User Agent is throwing error that 'request.UserAgent' threw an exception of type 'System.NotImplementedException'. Even i have hard coded useragent value also. Same case with other two params AllowAutoRedirect and CookieContainer. On the other hand all other params having correct value or null.
Any help on this, why UserAgent param is throwing this error 'request.UserAgent' threw an exception of type 'System.NotImplementedException'. Below is my web request:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri("TargetAPIIUrl_I am passing here"));
request.Method = "POST";
string boundary = "---------------" + DateTime.Now.Ticks.ToString();
string formDataBoundary = "-----------------------------" + DateTime.Now.Ticks.ToString().Substring(0, 14);
string contentType = "multipart/form-data; boundary=" + formDataBoundary;
request.ContentType = contentType;
request.UserAgent = "Hardcoded string of my target API";
request.BeginGetRequestStream(new AsyncCallback(asyncResult =>
{
Stream stream = request.EndGetRequestStream(asyncResult);
SilverlightApplication1.TubeUtility.DataContractMultiPartSerializer ser = new SilverlightApplication1.TubeUtility.DataContractMultiPartSerializer(boundary);
ser.WriteObject(stream, parameters);
stream.Close();
request.BeginGetResponse(callback, request);
}), request);
The UserAgent and AllowAutoRedirect properties are present to maintain some consistency with the .NET framework HttpWebRequest however neither the ClientHTTP nor the BrowserHTTP implementations support them.
It is possible to use a CookieContainer with the ClientHTTP stack, the BrowserHTTP stack will of course use the host browser cookie management.
I have a problem using google apps engine with google spreadsheet.
I Get the authorization token with another servlet (by google ClientLogin) and then i try to get the spreadsheet feed xml with GET request and Authorization header (as described by google documentation).
My servlet look like this:
public class My2Servlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
URLFetchService urlFetchService = URLFetchServiceFactory.getURLFetchService();
HTTPRequest tokenRequest = new HTTPRequest(new URL("http://localhost:8888/myGae/getauthtoken"), HTTPMethod.GET);
HTTPResponse tokenResponse = urlFetchService.fetch(tokenRequest);
String token = Utils.getText(tokenResponse.getContent()); /*this token is OK*/
HTTPRequest spreadsheetFeedRequest = new HTTPRequest(new URL("https://spreadsheets.google.com/feeds/spreadsheets/private/full"), HTTPMethod.GET);
spreadsheetFeedRequest.setHeader(new HTTPHeader("Authorization", "GoogleLogin auth=" + token));
HTTPResponse spreadsheetFeedResponse = urlFetchService.fetch(spreadsheetFeedRequest); /*here the problems!!!*/
String spreadsheetFeed = Utils.getText(spreadsheetFeedResponse.getContent());
resp.setContentType("text/plain");
resp.getWriter().println(spreadsheetFeed);
}
}
I can correctly have the token but when i try to do the second request to have the spreadsheet feed i have the error 400 Bad Request and if i retry to reload this error:
java.io.IOException: Could not fetch URL: https://spreadsheets.google.com/feeds/spreadsheets/private/full
It seems that only the first request work... in fact if I comment the second request and get the token then comment the first request and execute the second request with token hand-written I correctly have the spreadsheet feed xml output...
Why can't I perform two subsequent requests?
I have implemented google-oauth (3-legged) & used gdata client library. I am explaining only for FYI, as this not the solution but just a suggestion.
You can download it from here. See the documentation.
Then use the following code :
Get the Spreadsheet feed :
SpreadsheetFeed resultFeed = googleService.getFeed(feedUrl, SpreadsheetFeed.class);
if (resultFeed.getEntries().isEmpty()) {
out.println("<br/>|\tNo entries found.");
} else {
List<SpreadsheetEntry> spreadsheets = resultFeed.getEntries();
for (int i = 0; i < spreadsheets.size(); i++) {
SpreadsheetEntry entry = spreadsheets.get(i);
out.println("<br/>" + entry.getTitle().getPlainText());
}
}
I'm trying to send files to the blobstore using http requests.
First I made a button to call the createUploadUrl to get the upload url.
Then I made a client:
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(URL_FROM_CREATEUPLOADURL);
httpPost.setEntity(new StringEntity("value1"));
HttpResponse httpResponse = httpClient.execute(httpPost);
But I have 2 problems:
In dev mode: When I run the client it responses "Must call one of set*BlobStorage() first."
If I upload the app: The url changes every time I call it, so when I run the client it responses "HTTP/1.1 500 Internal Server Error"
What I'm doing wrong?
It sounds like you're trying to hard-code a single upload URL. You can't do that - you need to generate a new one for each file you want to upload.
You also need to make sure that you upload the file as a multipart message rather than using formencoding or a raw body. I'm not familiar with the Java APIs, but it looks like you're setting the raw body of the request.
apparently the entity must be a MultiPartEntity.
This is the client code to get the URL:
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(myDomain/mayServlet);
HttpResponse httpResponse = httpClient.execute(httpPost);
Header[] headers = httpResponse.getHeaders(myHeader);
for (int i = 0; i < headers.length; i++) {
Header header = headers[i];
if(header.getName().equals(myHeader))
uploadUrl = header.getValue();
This is the server code to return the URL:
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
String uploadUrl = blobstoreService.createUploadUrl(requestHandlerServlet);
resp.addHeader("uploadUrl", uploadUrl);
This is the client upload code:
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(uploadUrl);
MultipartEntity httpEntity = new MultipartEntity();
ContentBody contentBody = new FileBody(new File("filePath/fileName"));
httpEntity.addPart("fileKey", contentBody);
httpPost.setEntity(httpEntity);
HttpResponse httpResponse = httpClient.execute(httpPost);
so easy... :(