I'm currently making a custom API endpoint for a site that I'm building, which works absolutely fine aside from this issue with author ID's.
If I do a GET request to website.local/wp-json/wp/v2/podcasts it returns valid JSON of all of the podcasts Custom Post Type. If I do a GET request to website.local/wp-json/wp/v2/podcasts?author=1 it also returns valid JSON of all of the podcasts Custom Post Type - no problems here.
The problem however comes from some other code that I'm writing, I'm trying to do this in a custom function:
$server = rest_get_server();
$podcastsRequest = new WP_REST_Request( 'GET', '/wp/v2/podcasts?author=1');
$podcastsResponse = rest_do_request( $podcastsRequest );
$podcastsData = $server->response_to_data( $podcastsResponse, false );
When I run it in Postman I get the following response:
{
"code": "rest_no_route",
"message": "No route was found matching the URL and request method.",
"data": {
"status": 404
}
}
If I do this call internally inside the function, it works fine:
$server = rest_get_server();
$podcastsRequest = new WP_REST_Request( 'GET', '/wp/v2/podcasts');
$podcastsResponse = rest_do_request( $podcastsRequest );
$podcastsData = $server->response_to_data( $podcastsResponse, false );
I cannot work out why it's producing that error when a direct call to it works fine?
My approach to this was wrong, and I didn't understand the error properly. After taking another look at this, I was able to fix it by replacing this code:
if($request->get_param('id')){
// $author = $request->get_param('author');
$podcastsRequest = new WP_REST_Request( 'GET', '/wp/v2/podcasts?author=1');
$articlesRequest = new WP_REST_Request( 'GET', '/wp/v2/articles?author=1');
$webinarsRequest = new WP_REST_Request( 'GET', '/wp/v2/webinars?author=1');
$expertInterviewsRequest = new WP_REST_Request( 'GET', '/wp/v2/expert-interviews?author=1');
$guidesRequest = new WP_REST_Request( 'GET', '/wp/v2/guides?author=1');
} else {
$podcastsRequest = new WP_REST_Request( 'GET', '/wp/v2/podcasts?author=1' );
$articlesRequest = new WP_REST_Request( 'GET', '/wp/v2/articles?author=1' );
$webinarsRequest = new WP_REST_Request( 'GET', '/wp/v2/webinars?author=1' );
$expertInterviewsRequest = new WP_REST_Request( 'GET', '/wp/v2/expert-interviews?author=1' );
$guidesRequest = new WP_REST_Request( 'GET', '/wp/v2/guides?author=1' );
}
with this code:
if($request->get_param('author')){
$author = $request->get_param('author');
$podcastsRequest = new WP_REST_Request( 'GET', '/wp/v2/podcasts');
$podcastsRequest->set_query_params( array( 'author' => $author ));
$articlesRequest = new WP_REST_Request( 'GET', '/wp/v2/articles');
$articlesRequest->set_query_params( array( 'author' => $author ));
$webinarsRequest = new WP_REST_Request( 'GET', '/wp/v2/webinars');
$webinarsRequest->set_query_params( array( 'author' => $author ));
$expertInterviewsRequest = new WP_REST_Request( 'GET', '/wp/v2/expert-interviews');
$expertInterviewsRequest->set_query_params( array( 'author' => $author ));
$guidesRequest = new WP_REST_Request( 'GET', '/wp/v2/guides');
$guidesRequest->set_query_params( array( 'author' => $author ));
} else {
$podcastsRequest = new WP_REST_Request( 'GET', '/wp/v2/podcasts');
$articlesRequest = new WP_REST_Request( 'GET', '/wp/v2/articles');
$webinarsRequest = new WP_REST_Request( 'GET', '/wp/v2/webinars');
$expertInterviewsRequest = new WP_REST_Request( 'GET', '/wp/v2/expert-interviews');
$guidesRequest = new WP_REST_Request( 'GET', '/wp/v2/guides');
}
This now works as the API endpoint isn't directly set up to match additional parameters on itself, however passing them through with set_query_params() did the job!
My code is as follows:
require __DIR__.'/vendor/autoload.php';
use Psr\Http\Message\ResponseInterface;
$loop = React\EventLoop\Factory::create();
$client = new React\Http\Browser($loop);
$data = [
'name' => [
'first' => 'Alice',
'name' => 'Smith',
],
'email' => 'alice#example.com',
'userid' => 'alice',
];
$client->post(
'https://httpbin.org/post',
[
'Content-Type' => 'application/json',
],
json_encode($data)
)->then(function (ResponseInterface $response) {
$response = (string) $response->getBody();
return $response;
});
**echo $response;**
$loop->run();
I am able to get the response inside then function(). but I cannot retrieve the response value outside.
I like to send multiple asynchronous POST requests and collect each responses and echo all of them at once.
How can I access the response variable from outside of post()->then()?
I could get the response when I need a response with deferred and promise method.
First, I assigned the request and response method to $promise.
And I was able to simply get the response with $deferred->resolve();
require __DIR__.'/vendor/autoload.php';
use Psr\Http\Message\ResponseInterface;
$loop = React\EventLoop\Factory::create();
$client = new React\Http\Browser($loop);
$deferred = new React\Promise\Deferred();
$promise = $deferred->promise();
$data = [
'name' => [
'first' => 'Alice',
'name' => 'Smith',
],
'email' => 'alice#example.com',
'userid' => 'alice',
];
$promise = $client->post(
'https://httpbin.org/post',
[
'Content-Type' => 'application/json',
],
json_encode($data)
)->then(function (ResponseInterface $response) {
$response = (string) $response->getBody();
return $response;
});
echo $deferred->resolve();
$loop->run();
I´ve been searching a lot to find a solution but my problem as to do with some understanding of the mechanism, so i was wondering if someone could help me:
At this moment i´m sending push notifications using the REST api from OneSignal and it´s working...but i don´t know how to reach the data sent in order to tell the app to go to a specific place:
My server side:
public function sendMessage(){
$content = array(
"en" => 'Nova Angariação'
);
$hashes_array = array();
array_push($hashes_array, array(
"id" => "like-button",
"text" => "Ver",
"icon" => "http://i.imgur.com/N8SN8ZS.png",
"url" => "https://yoursite.com"
));
$fields = array(
'app_id' => "myAppId",
'included_segments' => array(
'All'
),
'data' => array(
"foo" => "bar"
),
'contents' => $content,
'buttons' => $hashes_array
);
$fields = json_encode($fields);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://onesignal.com/api/v1/notifications");
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json; charset=utf-8',
'Authorization: Basic my rest key'
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$resp = curl_exec($ch);
curl_close($ch);
return $resp;
}
Now in my app(i´m using nativescript with OneSignal SDK):
if (application.ios) {
const MyDelegate = /** #class */ (function (_super) {
__extends(MyDelegate, _super);
function MyDelegate() {
return _super !== null && _super.apply(this, arguments) || this;
}
MyDelegate.prototype.applicationDidFinishLaunchingWithOptions = function (app, launchOptions) {
try {
**//i think it´s here where i have to handle the handleNotificationOpened but i don´t know how**
TnsOneSignal.initWithLaunchOptionsAppId(launchOptions, 'my onesignal app key');
}
catch (error) {
console.error('error', error);
}
return true;
};
MyDelegate.ObjCProtocols = [UIApplicationDelegate];
return MyDelegate;
}(UIResponder));
application.ios.delegate = MyDelegate;
}
How do i do this?
Thanks for your time
Regards.
If you want to access the notification data upon app launch, then try this inside applicationDidFinishLaunchingWithOptions
if (launchOptions) {
const userInfo = launchOptions.objectForKey(UIApplicationLaunchOptionsRemoteNotificationKey);
if (userInfo) {
const aps = userInfo.objectForKey("aps");
if (aps !== null) {
// aps will be again a dictionary will have all data for the notification
}
}
}
Between didReceiveRemoteNotification also works, but when application is already in foreground.
I am trying to set an Authorization header with Guzzle/6.2.0 on Ubuntu 18.04.1. But I cannot set it. Can anyone help me with this problem?
I have following code:
use GuzzleHttp\Client;
$url = 'my_url';
$client = new Client();
$response = $client->get( $url, [
'headers' => [
'Authorization' => "Bearer {$my_token}"
]
]);
echo '<pre>';
print_r(json_decode($response->getBody(), true));
echo '</pre>';
The server returns all the headers from the request. Here in this function, the authorization header is no longer present.
return $this->handleView($this->view([
'headers' => $request->headers->all()
], 200));
And answer is:
Array {
[headers] => Array {
[host] => Array{ [0]=>'my_url' }
[user-agent] => Array { [0] => GuzzleHttp/6.2.0 curl/7.58.0 PHP/7.1.22-1+ubuntu18.04.1+deb.sury.org+1 }
[x-php-ob-level] => Array{ [0] => 1 }
}
}
So, "Authorization" was not setted.
Thank you!
Can you try with the debug option turned on? What do you see in the logs?
Also can you upgrade to the latest version? I don't remember any bugs related to the question, but if you want to report it in the end, you have to do it against the latest version.
I'm trying to upload image via Wordpress REST api v2. So far all I managed was to create empty entries in wordpress media library. Meaning they have image names, but no actual image.
POST Request:
http://localhost/wordpress/wp-json/wp/v2/media
Authorization: Basic d29yZHByZXNzOndvcmRwcmVzcw==
Content-Type: application/json
Content-Disposition: attachment;filename=map2.jpg
{
"source_url" : "file:///C:/Users/x/Desktop/map2.jpg"
}
Response:
{
"id": 127,
"date": "2016-05-25T08:43:30",
"date_gmt": "2016-05-25T08:43:30",
"guid": {
"rendered": "http://localhost/wordpress/wp-content/uploads/2016/05/map2-3.jpg",
"raw": "http://localhost/wordpress/wp-content/uploads/2016/05/map2-3.jpg"
},
"modified": "2016-05-25T08:43:30",
"modified_gmt": "2016-05-25T08:43:30",
"password": "",
"slug": "map2-3",
"status": "inherit",
"type": "attachment",
"link": "http://localhost/wordpress/map2-3/",
"title": {
"raw": "map2-3",
"rendered": "map2-3"
},
"author": 1,
"comment_status": "open",
"ping_status": "closed",
"alt_text": "",
"caption": "",
"description": "",
"media_type": "image",
"mime_type": "image/jpeg",
"media_details": {},
"post": null,
"source_url": "http://localhost/wordpress/wp-content/uploads/2016/05/map2-3.jpg",
"_links": {
"self": [
{
"href": "http://localhost/wordpress/wp-json/wp/v2/media/127"
}
],
"collection": [
{
"href": "http://localhost/wordpress/wp-json/wp/v2/media"
}
],
"about": [
{
"href": "http://localhost/wordpress/wp-json/wp/v2/types/attachment"
}
],
"author": [
{
"embeddable": true,
"href": "http://localhost/wordpress/wp-json/wp/v2/users/1"
}
],
"replies": [
{
"embeddable": true,
"href": "http://localhost/wordpress/wp-json/wp/v2/comments?post=127"
}
]
}
}
I get no errors, everything's seem to be working, except response->post and response->media_details is either null or empty. Ofcourse image itself is not uploaded.
Based on this GitHub WP-API Adding Media ticket, I should send 2 requests. First POST request should return data with post object. I would send this post object via PUT method, and image should be uploaded...since I have no post object, this is not possible.
Any ideas what am I doing wrong?
Sideloading images is not supported by the wordpress api so you will have to do some changes.
First, your content-type should be image/jpeg and not application/json, remember that content-type is supposed to reflect the data that you are passing and the POST media request expects an image.
Another change you have to make to accommodate the content-type is the way that you are passing the data. Instead of sending it with the source_url parameter, try passing it as a binary file.
One last thing I would mention is that the wp/v2 calls return 3XX status on a few occasions. It would be useful to follow those redirects and redo those requests to those new urls.
I had some issues passing JPEG images but PNG images have worked well. Here is a curl example that I use to upload png media:
curl --request POST \
--url http://www.yoursite.com/wp-json/wp/v2/media \
--header "cache-control: no-cache" \
--header "content-disposition: attachment; filename=tmp" \
--header "authorization: Basic d29yZHByZXNzOndvcmRwcmVzcw==" \
--header "content-type: image/png" \
--data-binary "#/home/web/tmp.png" \
--location
My working answer using PHP cUrl
<?php
$curl = curl_init();
$data = file_get_contents('C:\test.png');
curl_setopt_array($curl, array(
CURLOPT_URL => "http://woo.dev/wp-json/wp/v2/media",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => array(
"authorization: Basic XxxxxxxXxxxxXx=",
"cache-control: no-cache",
"content-disposition: attachment; filename=test.png",
"content-type: image/png",
),
CURLOPT_POSTFIELDS => $data,
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
At january 2020 using wordpress 5.3.2 with nginx the solution that work for me is:
function uploadFile($token, $archivo) {
$file = file_get_contents( $archivo );
$mime = mime_content_type( $archivo );
$url = BASEAPI. 'wp-json/wp/v2/media';
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, 1 );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt( $ch, CURLOPT_POSTFIELDS, $file );
curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
'Content-Type: '.$mime,
'Content-Disposition: attachment; filename="'.basename($archivo).'"',
'Authorization: Bearer ' .$token,
] );
$result = curl_exec( $ch );
curl_close( $ch );
print_r( json_decode( $result ) );
}
The token is the Authorization JWT token and $archivo is the path to file.
For anyone looking for a JS solution, here's how I made it work using Axios. I will skip authorization implementations, as there are a few options around (oAuth, JWT, Basic).
const fs = require('fs');
const axios = require('axios');
axios({
url: 'http(s)://{your-wp-domain}/wp-json/wp/v2/media',
method: 'POST',
headers: {
'Content-Disposition':'attachment; filename="file.jpg"',
Authorization: {your-authorization-method},
'Content-Type':'image/jpeg'
},
data: fs.readFileSync('path/to/file.jpg', (err, data) => {
if (err) {
console.log(err);
}
});
})
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err);
});
Here you can use this code snippet. This works for me using Wordpress API REST
<?php
//Add this to your function.php
function upload_image( $imageID, $login ) {
$request_url = 'https://DOMAINNAME.com/wp-json/wp/v2/media'; //change the domainname
$image_file_path = get_attached_file($imageID); //change this to your file meda path if your not throwing media file to other server
$image = file_get_contents( $image_file_path );
$mime = mime_content_type( $image_file_path );
$api_media_response = wp_remote_post( $request_url, array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( $login ), //login format USERNAME:PASSWORD
'Content-Disposition' => 'attachment; filename='.basename($image_file_path).'',
'Content-Type' => $mime
),
'body' => $image
) );
//this function return wp_remote_post
// more info => https://developer.wordpress.org/reference/functions/wp_remote_post/
}
After trying to get the image upload running with wp_remote_post (don´t wanna use curl for several reasons) i came up with the following working solution:
// Upload image to wordpress media library
$file = #fopen( 'image.jpg', 'r' );
$file_size = filesize( 'image.jpg' );
$file_data = fread( $file, $file_size );
$args = array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( 'USERNAME:PASSWORD' ),
'accept' => 'application/json', // The API returns JSON
'content-type' => 'application/binary', // Set content type to binary
'Content-Disposition' => 'attachment; filename=nameoffileonserver.jpg'
),
'body' => $file_data
);
$api_response = wp_remote_post( 'http://myserver.com/wp-json/wp/v2/media', $args);
if you want to upload a image to WordPress rest API using nuxtjs or vuejs you can use the below code:
in template:
<input style="display: none;" type="file" #change="onFileSelected"
<button #click="onUpload" />
in data:
data() {
return {
selectedFile: null,
previewImage: null
};}
in methods:
onFileSelected(event) {
this.selectedFile = event.target.files[0];
}
onUpload() {
const fd = new FormData();
fd.append("file", this.selectedFile, this.selectedFile.name);
fd.append("title", "pedram");
fd.append("caption", "this is caption");
/* file reader for prview image */
const reader = new FileReader();
reader.readAsDataURL(this.selectedFile);
reader.onload = e =>{
this.previewImage = e.target.result;
};
/* set request header */
const headers = {
'Content-Disposition':`attachment; filename=${this.selectedFile.name}`,
Authorization: "Bearer" + this.$cookiz.get("AdminToken"),
'content-type': 'image'
};
this.$axios.post('/wp-json/wp/v2/media', fd, { headers })
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
},
if you want to preview the image you can use file reader and store it in a data variable then use the data instead of image src like bellow code:
<img #click="$refs.fileInput.click()" v-if="previewImage" :src="previewImage" alt="" class="w-100" />
It took me one day to solve the issue I hope the above codes helps