Brightcove Media API Access-Control-Allow-Origin - brightcove

I'm attempting to call the Media API but am getting an Access-Control-Allow-Origin error.
I tried appending '?jsoncallback=?' to my url (JSONP) and it now returns the JSON file but my browser is trying to interpret it as javascript and throwing an error.
(function() {
var mediaAPI = "http://api.brightcove.com/services/library?jsoncallback=?";
$.getJSON( mediaAPI, {
command: "find_video_by_id",
video_id: "2472866007001",
video_fields: "videoStillURL,thumbnailURL",
media_delivery: "http",
token: "4kDMVfqenhDk_uU2MvV8fioVrHsHwiKWCLFuxZumIq7fSa3wyRkTNw..",
format: "json"
})
.done(function( data ) {
var obj = jQuery.parseJSON(data);
alert( obj.name === "videoStillURL" );
});
})();

If you use callback instead of jsoncallback the Media API will return a JSONP response (JSON wrapped in a callback function)
You shouldn't use jQuery.parseJSON() with that type of response, alert(obj.videoStillURL) will work.

Change format: "json" to format: "jsonp"... should fix it for you

Related

NativeScript Vue send request with form data (multipart/form-data)

I have a case in my application where I need to send data as form data to a server. The data includes a message and an optional list of files. The problem I'm facing is that when sending the request it's not being formed properly.
Request Payload
Expected (sample with the same request in the browser)
Actual (resulting request when running in NativeScript)
The actual result is that the payload is somehow being URL encoded.
Code example
sendData({ id, message, files }) {
const config = {
headers: {
'Content-Type': 'multipart/form-data'
}
};
const payload = new FormData();
payload.append('message', message);
if (files && files.length > 0) {
files.forEach((file) => {
payload.append(`files`, file, file.name);
});
}
return AXIOS_INSTANCE.post(
`/api/save/${id}`,
payload,
config
);
}
As you can see from the above, I'm using axios and also I'm trying to use FormData to format the data. From my research it seems that NativeScript used to not support binary data via XHR - however looking at this merge request on GitHub it looks like it's been fixed about a year ago.
So my suspicion is that I'm doing something wrong, maybe there's an alternative to using FormData, or else I shouldn't use axios for this particular request?
Version Numbers
nativescript 6.8.0
tns-android 6.5.3
tns-ios 6.5.3
Nativescript's background-http supports multipart form data.
See below for how its configured to do multipart upload
var bghttp = require("nativescript-background-http");
var session = bghttp.session("image-upload");
var request = {
url: url,
method: "POST",
headers: {
"Content-Type": "application/octet-stream"
},
description: "Uploading "
};
var params = [
{ name: "test", value: "value" },
{ name: "fileToUpload", filename: file, mimeType: "image/jpeg" }
];
var task = session.multipartUpload(params, request);

Can't upload image to a external API using axios

I've been trying to upload an image with axios to an external (laravel) api and it's been giving me nightmares.
resumed template:
<v-form>
<v-file-input
label="Logo*"
v-model="image"
accept="image/*"
#change="onFileSelected"
required
></v-file-input>
<v-btn color="blue darken-1" text #click="createProvider">Create Provider</v-btn>
</v-form>
Methods
methods: {
onFileSelected (event) {
this.selectedImage = event;
},
createProvider() {
let formData = new FormData();
formData.append("image", this.selectedImage, this.selectedImage.name);
const config = {
headers: {
Authorization: this.token,
'content-type': 'multipart/form-data'
}
};
let imageData = {
'image': formData,
'name': 'Provider Image', // Required Field
}
axios.post('http://fake_external_url.com/api/images', imageData, config) // laravel API
.then(console.log)
.catch(console.log)
},
}
The error that I get in return is:
Error: Request failed with status code 422
Request Response:
[HTTP/1.1 422 Unprocessable Entity 1374ms]
{"image":{},"name":"Image Provider"}
I see that the image is not receiving anything.
If I console.log this.selectedImage I get:
File {
name: "happy.jpg",
lastModified: 1596711013544,
webkitRelativePath: "",
size: 41292,
type: "image/jpeg"
}
If I console.log FormData I get crap
FormData
​<prototype>: FormDataPrototype
​​append: function append()
​​constructor: function ()
​​delete: function delete()
​​entries: function entries()
​​forEach: function forEach()
​​get: function get()
​​getAll: function getAll()
​​has: function has()
​​keys: function keys()
​​set: function set()
​​values: function values()
​​Symbol(Symbol.toStringTag): "FormData"
​​Symbol(Symbol.iterator): function entries()
​​<prototype>: Object { … }
My environment: localhost on a XAMPP server (php artisan serve as well). Laravel, VueJS, Vuetify latest versions.
I think my problem likes in my FormData, but it may be from the variables that it's receiving from the event click. I am out of ideas.
[EDIT] Note: I am able to upload image when using POSTMAN.
The reason why I am using event, and not the classic event.target.files[0] it's because there is no target in the response from the console.log.
You have two problems.
FormData
You need to send a FormData object, only a FormData object, and nothing but a FormData object.
If you want to pass additional data, then append it to the FormData object.
Wrapping the FormData object in another object and passing it to (for example) a JSON serializer will just break it.
Content-Type
The multipart/form-data MIME type has a mandatory boundary parameter.
You have omitted it, but you can't know what it is anyway.
Do not set the Content-Type header manually. The underlying XHR object will read it from the FormData object.

POST binary data from browser to JFrog / Artifactory server without using form-data

So we get a file (an image file) in the front-end like so:
//html
<input type="file" ng-change="onFileChange">
//javascript
$scope.onFileChange = function (e) {
e.preventDefault();
let file = e.target.files[0];
// I presume this is just a binary file
// I want to HTTP Post this file to a server
// without using form-data
};
What I want to know is - is there a way to POST this file to a server, without including the file as form-data? The problem is that the server I am send a HTTP POST request to, doesn't really know how to store form-data when it receives a request.
I believe this is the right way to do it, but I am not sure.
fetch('www.example.net', { // Your POST endpoint
method: 'POST',
headers: {
"Content-Type": "image/jpeg"
},
body: e.target.files[0] // the file
})
.then(
response => response.json() // if the response is a JSON object
)
You can directly attach the file to the request body. Artifactory doesn't support form uploads (and it doesn't look like they plan to)
You'll still need to proxy the request somehow to avoid CORS issues, and if you're using user credentials, you should be cautious in how you treat them. Also, you could use a library like http-proxy-middleware to avoid having to write/test/maintain the proxy logic.
<input id="file-upload" type="file" />
<script>
function upload(data) {
var file = document.getElementById('file-upload').files[0];
var xhr = new XMLHttpRequest();
xhr.open('PUT', 'https://example.com/artifactory-proxy-avoiding-cors');
xhr.send(file);
}
</script>
Our front-end could not HTTP POST directly to the JFrog/Artifactory server. So we ended up using a Node.js server as a proxy, which is not very ideal.
Front-end:
// in an AngularJS controller:
$scope.onAcqImageFileChange = function (e) {
e.preventDefault();
let file = e.target.files[0];
$scope.acqImageFile = file;
};
// in an AngularJS service
createNewAcqImage: function(options) {
let file = options.file;
return $http({
method: 'POST',
url: '/proxy/image',
data: file,
headers: {
'Content-Type': 'image/jpeg'
}
})
},
Back-end:
const express = require('express');
const router = express.Router();
router.post('/image', function (req, res, next) {
const filename = uuid.v4();
const proxy = http.request({
method: 'PUT',
hostname: 'engci-maven.nabisco.com',
path: `/artifactory/cdt-repo/folder/${filename}`,
headers: {
'Authorization': 'Basic ' + Buffer.from('cdt-deployer:foobar').toString('base64'),
}
}, function(resp){
resp.pipe(res).once('error', next);
});
req.pipe(proxy).once('error', next);
});
module.exports = router;
not that we had to use a PUT request to send an image to Artifactory, not POST, something to do with Artifactory (the engci-maven.nabisco.com server is an Artifactory server). As I recall, I got CORS issues when trying to post directly from our front-end to the other server, so we had to use our server as a proxy, which is something I'd rather avoid, but oh well for now.

Angular $http jsonp: how to parse through data

I'm starting to learn Angular and I want to play around with the $http call function.
I basically want to make a get request to an external API:
angular.module('pokedexApp')
.controller('MainCtrl', function ($scope, $http) {
var response;
$http.jsonp("http://pokeapi.co/api/v1/pokemon/1/").success(function(response) {
response = response;
})
$scope.pokemon = response;
});
I'm probably completely wrong as to how this works. I basically want to {{ pokemon }} out a response to test it.
I'm getting a Uncaught SyntaxError: Unexpected token : error and I can't tell if it's because the return data isn't properly formatted or what.
The error is because in angular it will try to parse this response in json type. And it failed to parse, so it throw an error:
Uncaught SyntaxError: Unexpected token :
Seems in angularjs you'd better to handler jsonp response by your self.
$scope.triggerJsonp = function(){
$http.jsonp("http://pokeapi.co/api/v1/pokemon/1/", {params: {'callback':'eqfeed_callback'}});
};
window.eqfeed_callback = function(data){
$scope.response = data;
}
Here is jsfiddle.
Relative issue in jquery.ajax JSONP call showing "Uncaught SyntaxError: Unexpected token : " And answer use own callback to handle this.
It doesn't look like the website provides JSONP support - https://github.com/phalt/pokeapi_issues/issues/30
Your $http request is fine but you currently have a scoping issue with respect to 'response'. This is how your code should be written in order for your scope variable to be defined correctly:
angular.module('pokedexApp')
.controller('MainCtrl', function ($scope, $http) {
$http.jsonp("http://pokeapi.co/api/v1/pokemon/1/").success(function(response) {
$scope.pokemon = response;
})
});

Filter to detect if Response::json was sent

I have a filter. I want this filter to act only if the page is displaying HTML and NOT if it's json or any other format
App::after(function($request, $response)
{
if( $request->getMethod() == 'GET' && $request->getRequestFormat() == 'html' ) {
// do something!
}
});
In my Controller functions I return json data:
return Response::json($data);
However, $request->getRequestFormat() is still equal to 'html' and it shouldn't be.
I know that I can set the format to be 'json' like this:
Request::setRequestFormat('json');
return Response::json($data);
But it seems redundant. If I'm returning a Response::json it should know that it's json and not HTML. How can I detect that it's a Response::json?
The requestFormat is something that isn't set automatically - you either provide it programattically via setRequestFormat or by including a POST/GET parameter _format.
If you want to check if a request is JSON you can do $request->isJson(), but it looks more to me like you're trying to check if the response is JSON? In which case you can do $response instanceof Illuminate\Http\JsonResponse or $response->headers->get('Content-Type') == 'application/json'
This is not a json at all, it's HTML which contains some string inside a div. Remove the div and just pass the json using:
return Response::json($data);
Then in the client side, using jQuery parse the json data and create a div and append the data inside div, for example, in your success callback try something like this:
success(response) {
// Parse the json if not parsed by jQuery
var obj = $.parseJSON(response);
if(obj.success) {
$('<div/>', {id:"query-log"}).append(obj.data).appendTo('body');
}
}
This may not accurate with your json data but hope you got the idea, in short, just pass the json data to the client side and manipulate it in the browser using jQuery.
Update: The better approach would be to provide the dataType when making the request using something like tgis:
$.ajax({
dataType: "json",
url: url,
data: data,
success: function( data ) {
}
});
Also you may use this:
$.getJSON( "url", function( data ) {
// ...
});
So a request header will be sent to the server and you may check if the request is expecting a json response using this:
if($request->wantsJson()) {
//
}
This is the method in the request class:
/**
* Determine if the current request is asking for JSON in return.
*
* #return bool
*/
public function wantsJson()
{
$acceptable = $this->getAcceptableContentTypes();
return isset($acceptable[0]) && $acceptable[0] == 'application/json';
}
App::after(function($request, $response)
{
if( $request->getMethod() == 'GET' && $request->getRequestFormat() == 'html' ) {
// Test if response is JSON (PHP 5.3+ needed for this)
json_decode($response);
if ( json_last_error() != JSON_ERROR_NONE ) {
// Do something
}
}
});

Resources