Posting Yammer message with attachment - yammer

I cannot figure out what fields or tags Yammer expects for my post variables when trying to post an attachment using the messages API. Yammer documentation says:
"The first method is the easiest, simply use file form elements with names attachment1 through attachment20. If there are a several attachments or the attachments are large it may take some time for a message to POST causing your application to appear to hang."
I read through the specification they said they are using RFC 1867 but still cannot get a simple text file or url (shown below) to post as an attachment. If I take out the attachement1 variable in the post array $jtext then the body of the message will post as expected.
I'm also not entirely sure that this should be a multi-dim array.
Any help is appreciated!
This is written in PHP.
$jtext=array("body"=>$text,
"attachment1"=>array("type"=>"file","name"=>"https://www.google.com/"));
$url="https://www.yammer.com/api/v1/messages.json";
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$jtext);
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer '.$accToken,'Content-Type: multipart/form-data'));
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$result = curl_exec($ch);

I have had better luck using the pending attachments resource. It's 2 steps, so it might help you to see where you are getting stuck.
Try to send the file to the pending attachments resource first with POST https://www.yammer.com/api/v1/pending_attachments.
If it was successful, you receive an id for the attachment, and then just send the id as pending_attachment1 -pending_attachment20 or however many you are attaching with the new message endpoint.

Related

POST a JSON and a CSV in a multipart/form-data request through a NiFi 1.15 InvokeHTTP processor

I'm working on a NiFi 1.15 flow where I have to send a request to a service that requires 2 pieces of form-data sent in a POST request as a multipart/form-data. The first part is a simple JSON object with a few parameters, while the second part is a CSV file. Here is an example of what I am trying to achieve.
Content-Type: multipart/form-data; boundary=1cf28ed799fe4325b8cd0637a67dc612
--1cf28ed799fe4325b8cd0637a67dc612
Content-Disposition: form-data; name="json"; filename="json"
{"Param1": "Value1","Param2": "Value2","Param3": true}
--1cf28ed799fe4325b8cd0637a67dc612
Content-Disposition: form-data; name="file"; filename="body.csv"
Field1,Field2,Field3,Field4,Field5
VALUE_FIELD_1,VALUE_FIELD_2,VALUE_FIELD_3,"Some value for field 4",VALUE_FIELD_5
--1cf28ed799fe4325b8cd0637a67dc612--
Another acceptable output would have the Content-Disposition lines empty.
Due to a few restrictions in the environment I am working on, I am not allowed to use scripting processors, such as ExecuteGroovyScript as suggested in another SO question.
Instead, I started creating a GenerateFlowFile -> InvokeHTTP flow. The GenerateFlowFile would output to a flow file a text similar to the one mentioned above. Here is the screenshot of the GenerateFlowFile.
The connected InvokeHTTP processor is configured to use the POST Http Method and to send headers (the Authorization header in my case) and Send Message Body is set to true. It also extracts the Content-Type from the flow file previsously generated attribute through a ${mime.type} function. You can see the details in the following screenshots.
Sadly, this does not work. The server responds with an "Unexpected end of MIME multipart stream. MIME multipart message is not complete." error.
After searching for a while in SO, I found another question describing what looks like a similar problem, but there they are getting a different error and is also posting parameters through a different method.
I am also aware about the blog post from Otto Fowler where he shows how InvokeHTTP supports POSTs with multipart/form-data. I did try this approach too, but did not manage to get it working. The service throws an error stating that NiFi does not send one of my post:form:parts.
Right now I am stuck and am not able to send that data. I did manage to write a simple Python script to test if the server is working properly and it is. For reference, here is the script:
import requests
server = 'https://targetserver.com'
#Authentication
result = requests.post(server + '/authentication',
{'grant_type': 'password',
'username': 'username',
'password': 'password'})
token = result.json()['access_token']
#Build the request
headers = {'Authorization': 'bearer ' + token}
json_data = '{"Param1": "Value1","Param2": "Value2","Param3": true}'
# First the JSON then the csv file.
files = {'json': json_data,
'file': open('body.csv', 'rb')}
result = requests.post(server + '/endpoint', headers = headers, files = files)
print(result.text)
Does anyone have a suggestion on how to get around this situation?

How to use PUT method in Laravel API with File Upload

Having read this SO link,
PUT is most-often utilized for update capabilities, PUT-ing to a known resource URI with the request body containing the newly-updated representation of the original resource.
From this answer,
... we need to send all the parameters of the data again.
In my controller, I have:
$student = Student::find($student_id);
$student->username = $request->username;
$student->email = $request->email;
$student->password = $request->password;
$path = $request->file('passport')->store('upload');
$student->passport = $path;
I have once used this same code for POST method and it worked, but while using it for APIs, I used POSTMAN form-data and got $request->all() to be null. Some said I should use x-www-form-urlencoded but this does not allow files upload.
This is actually an incapability of PHP itself. A PUT/PATCH request with multipart/form-data just will not populate $_FILES, so Laravel has nothing to work with.
Every once in a while, people report bugs like this when they find $request->all() returns null, thinking it's Laravel's fault, but Laravel can't help it.
Files are best sent as multipart/form-data and that sort of request will only populate $_FILES if it's a POST. No $_FILES, no $request->file().
In lieu of having this work as-expected in PHP, if it works using a POST, just use a POST.
When the form contains uploaded file it works only with POST method - probably an issue with PHP/Laravel
If someone wants to use a PUT or PATCH request for form containing file uploads
<form action="/foo/bar" method="POST">
#method('PUT')
...
</form>
via any javascript framework like vue
let data = new FormData;
data.append("_method", "PUT")
axios.post("some/url", data)
Using _method and setting it to 'PUT' or 'PATCH' will allow to declare route as a PUT route and still use POST request to submit form data
I have answered a similar question How to update image with PUT method in Laravel REST API?

Nested Request with JSON

I am trying to decode a request that comes from Twilio in Laravel 5.
It comes as application/x-www-form-urlencoded, but it has a JSON payload in it with data that I want to access called Memory.
How do I access it in Laravel?
Twilio developer evangelist here.
As you're looking at memory, I'm guessing you're using Twilio Autopilot. In that case, you should get the Memory field from the request and then parse it as JSON data.
$rawMemory = $request->input('Memory');
$memory = json_decode($rawMemory, true);
You probably just need to get the content from the request, which should contain the JSON.
$requestData = json_decode($request->getContent(), true);
dd($requestData);

Laravel download pdf file stored in separate Laravel app

I have 2 Laravel(5.8) apps. One is a user application, the other is more of an API.
The Api has pdfs stored in the storage directory, I need to be able to allow a user to download the pdfs in the other application.
Really got no clue how to send the file over from app to the other.
The user app makes an api to the api with relevant file ids and things (fine), just can't work out how to send the file back, and then download it on the other end.
Tried things like return response()->stream($pdf) on the api and return response()->download($responeFromApiCall) and loads of other things but really getting nowhere fast.
Any advice welcome.
The laravel code you posted is basically correct, you can use one of stream(), download() or file() helper to serve a file.
file()
Serve a file using a binary response, the most straightforward solution.
// optional headers
$headers = [];
return response()->file(storage_path('myfile.zip'), $optionalHeaders);
You can also use your own absolute file path instead of the storage_path helper.
download()
The download helper is similar to file(), but it also sets a Content-Disposition header which will result in a download-popup if you retrieve the file using your browser.
$location = storage_path('myfiles/invoice_document.pdf');
// Optional: serve the file under a different filename:
$filename = 'mycustomfilename.pdf';
// optional headers
$headers = [];
return response()->download($location, $filename, $headers);
stream()
The stream() helper is a bit more complex and results in reading and serving a file in chunks. This can be used for situations where the filesize is unknown (like passing through another incoming stream from an API). It results in a Transfer-Encoding: chunked header which indicates that the data stream is divided into a series of non-overlapping chunks:
// optional status code
$status = 200;
// optional headers
$headers = [];
// The stream helper requires a callback:
return response()->stream(function() {
// Load a file from storage.
$stream = Storage::readStream('somebigfile.zip');
fpassthru($stream);
if(is_resource($stream)) {
fclose($stream);
}
}, $status, $headers);
Note: Storage::readStream takes the default storage disk as defined in config/filesystems.php. You can change disks using Storage::disk('aws')->readStream(...).
Retrieving your served file
Say your file is served under GET example.com/file, then another application can retrieve it with curl (assuming PHP). A popular wrapper for this would be Guzzle:
$client = new \GuzzleHttp\Client();
$file_path = __DIR__ . '/received_file.pdf';
$response = $client->get('http://example.com/file', ['sink' => $file_path]);
You can derive the filename and extension from the request itself by the way.
If your frontend is javascript, then you can retrieve the file as well but this another component which I dont have one simple example for.
So if I understand correctly you have two systems: user app and api. You want to serve a pdf from user app to the actual user. The user app does a call to api, which works fine. Your issue is converting the response of the api to a response which you can serve from your user app, correct?
In that case I'd say you want to proxy the response from the api via the user app to the user. I don't know what the connection between the user app and the api is, but if you use Guzzle you could look at this answer I posted before.
Here are the steps you should follow to get the PDF:
Make an API call using AJAX ( you are probably already doing it ) from your public site ( User site ) to the API server, with file ID.
API server fetches the PDF, copy it to the public/users/ directory, generate the URL of that PDF file.
Send the URL as a response back to the User site. Using JS add a button/ link in the DOM, to that PDF file.
Example:
jQuery.post(ajaxurl, data, function(response) {
var responseData = JSON.parse(response);
var result = responseData.result;
var pdf_path = responseData.pdf_path;
$(".nametag-loader").remove();
$(".pdf-download-wrapper").append("<a class='download-link' href='"+ pdf_path +"' target='_blank'>Download</a>");
});

Mathematica 8.0 interaction with a web server JSP using HTTP POST and XML

I have been tasked with using Mathematica to interact with a third party's web server via JSP using HTTP POST and XML. Example of what I need to send:
<html>
<head></head>
<body>
<form method="post" action="http://www. ... .com/login.jsp">
<textarea name="xml" wrap="off" cols="80" rows="30" spellcheck="false">
<loginInfo>
<param name="username" type="string">USERNAME</param>
<param name="pwd" type="string">PASSWORD</param>
</loginInfo>
</textarea>
<input type="hidden" name="Login" value="1"/>
<input type="submit" name="go" value="go" />
</form>
</body>
</html>
Example of what I will receive (XML):
<UserPluginInfo>
<PluginInfo>
<param name="pluginUid" type="string">1</param>
</PluginInfo>
<UserInfo>
<param name="username" type="string">USERNAME</param>
</UserInfo>
</UserPluginInfo>
I found a blog by Robert Raguet-Schofield written in 2009 about interacting with Twitter that uses J/Link to access Java to perform the HTTP POST and handle the response.
My question is, is this the best method to accomplish my task or has Mathematica evolved since 2009 and there is a better way (more straight forward) to accomplish my task?
Whilst this may not be a better way, an alternative approach to circumvent the need of J/Link would be to set up an intermediate CGI script to translate the request from GET to POST for you.
This script file would sit on an accessible server, it would take the specified GET query, make a POST request on the target page, then output/return the result XML in the normal way.
For example, using curl in PHP that would work well - although obviously it would be possible to achieve the same functionality in pretty much any CGI language.
<?php
$c = curl_init();
// set the various options, Url, POST,etc
curl_setopt($c, CURLOPT_URL, "http://www. ... .com/login.jsp"); // Target page
curl_setopt($c, CURLOPT_HEADER, false);
curl_setopt($c, CURLOPT_POST, true);
curl_setopt($c, CURLOPT_RETURNTRANSFER, false);
// POST the incomming query to the Target Page
curl_setopt($c, CURLOPT_POSTFIELDS, $_SERVER['QUERY_STRING']);
curl_exec($c);
curl_close($c);
// Output the XML response using header/echo/etc...
// You might need to also send some of the POST request response headers
// use CURLOPT_HEADER to access these...
?>
From the Mathmatica stand point this is much simpler as you simply use the built in import method to make a standard GET request on the proxy page but get the result XML from a POST request on the login page.

Resources