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... :(
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.
I am using AWS API Gateway with a Java Lambda Backend.
Everything is peachy until a friend using Angular 4 is trying to make requests. He keeps getting:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at URL (Reason: CORS header
'Access-Control-Allow-Origin' missing).
I have enabled CORS via the gateway:
Despite this the error remains. What should I modify ?
Thanks.
Ian's Comments:
I use Output/Input Streams so my output, as per your comment I am trying as below but still no success. Any ideas ?
private void sendResponse(JSONObject body, int statusCode, OutputStream outputStream)
{
OutputStreamWriter writer;
JSONObject responseJson = new JSONObject();
JSONObject responseHeadersJson = new JSONObject();
responseHeadersJson.put("Access-Control-Allow-Origin","*");
responseHeadersJson.put("Access-Control-Allow-Headers","Content-Type");
responseJson.put("headers",responseHeadersJson);
responseJson.put("statusCode", statusCode);
responseJson.put("body", body.toJSONString());
try {
writer = new OutputStreamWriter(outputStream, "UTF-8");
writer.write(responseJson.toJSONString());
writer.close();
} catch (IOException e) {
System.out.println("Outputstream Error "+e);
}}
I can see that you are using Proxy Resource.
That means you are controlling the response thats going back as well from your Lambda. CORS needs to be configured on the response as well by adding the origin header.
When you build the response you need to add the cors headers by passing the domain or *.
I have built a ResponseBuilder that you can use as an example:
https://github.com/ahpoi/commons-utils-sdk/blob/master/src/main/java/com/ahpoi/commons/utils/aws/lambda/model/proxy/response/ResponseBuilder.java
public ResponseBuilder originHeader(String domain) {
headers.put(ACCESS_CONTROL_ALLOW_ORIGIN, domain);
return this;
}
private void initDefaultHeaders() {
headers.put(ACCESS_CONTROL_ALLOW_HEADERS, "Content-Type");
}
public Response build() {
this.initDefaultHeaders();
return new Response(statusCode, headers, body);
}
If you didn't use Proxy Resource, your configuration would have been enough.
I am currently using a Get Request with proxy information:
String result1 = Request.Get("_http://somehost/")
.version(HttpVersion.HTTP_1_1)
.connectTimeout(1000)
.socketTimeout(1000)
.viaProxy(new HttpHost("myproxy", 8080))
.execute().returnContent().asString();
The result is a "Proxy Authentication Required" error. I believe a username and password is required from the server making the request? If so, how do I add that detail? I have never used the Fluent API before.
Here is an example using the Fluent API. The executor can be used to specify credentials for the proxy.
HttpHost proxyHost = new HttpHost("myproxy", 8080);
Executor executor = Executor.newInstance()
.auth(proxyHost, "username", "password");
String result1 = executor.execute(Request.Get("_http://somehost/")
.viaProxy(proxyHost))
.returnContent()
.asString();
You need a CredentialsProvider.
final CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials(username, password));
final HttpPost httppost = new HttpPost(uri);
httppost.setConfig(RequestConfig.custom().setProxy(proxy).build());
String line = HttpClientBuilder.create().setDefaultCredentialsProvider(credsProvider).build() .execute(httppost).getStatusLine());
Also, there was a bug in 4.3.1 that impacted authentication. It is fixed in 4.3.2.
https://issues.apache.org/jira/browse/HTTPCLIENT-1435
Executor executor = Executor.newInstance()
.auth(new HttpHost("myproxy", 8080), "username", "password")
.authPreemptive(new HttpHost("myproxy", 8080));
Response response = executor.execute(<your reques>);
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.
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());
}
}