Detect WordPress REST API response? - wordpress

What is the best way of detecting whether a WordPress response was generated by the REST API? There don't yet appear to be any conditional tags like is_feed() or is_page()?
Some hooks late in the WordPress lifecycle may alter output, such as naively appending html tags or debugging content. The problem is, if the response is a JSON blob from the REST API, appending content will invalidate the JSON response.
The is_feed conditional tag doesn't recognize REST API responses as feeds and returns false.

The rest_api_loaded method in wp-includes/rest-api.php defines a REST_REQUEST constant, that's helpfully labeled "Whether this is a REST Request". That constant then gets checked in class-wp-query.php. Here's a simple little is_rest conditional function based on that check:
function is_rest() {
return ( defined( 'REST_REQUEST' ) && REST_REQUEST );
}

Related

How to list all parameters available to query via API?

As a end-point user of an API, how can I list all parameters available to pass the query? In my case (stats about Age of Empires 2 matches), the website describing the API has a list with some of them but it seems there are more available.
To provide more context, I'm extracting the following information:
GET("https://aoe2.net/api/matches?game=aoe2de&count=1000&since=1632744000&map_type=12")
but for some reason the last condition, map_type=12 does nothing (output is the same as without it). I'm after the list of parameters available, so I can extract what I want.
PD: this post is closely related but does not focus on API. Perhaps this makes a difference, as the second answer there seems to suggest.
It is not possible to find out all available (undocumented) query parameters for a query, unless the API explicitly provides such a method or you can find out how the API server processes the query.
For instance, if the API server code is open source, you could find out from the code how the query is processed. Provided that you find the code also.
The answers in the post you linked are similarly valid for an API site as well as for one that provides content for a web browser (a web server can be both).
Under the hood, there is not necessarily any difference between an API server or a server that provides web content (html) in terms of how queries are handled.
As for the parameters seemingly without an effect, it seems that the API in question does not validate the query parameters, i.e., you can put arbitrary parameters in the query and the server will simply ignore parameters that it is not specifically programmed to use.
The documentation on their website is all any of us have to go by https://aoe2.net/#api
You can't just add your own parameters to the URL and expect it to return a value back as they have to have coded it to work that way.
Your best bet is to just extract as much data as you can by increasing the count parameter, then loop through the JSON response and extract the map_type from there.
JavaScript example:
<script>
json=[{"match_id":"1953364","lobby_id":null,"game_type":0},
{"match_id":"1961217","lobby_id":null,"game_type":0},
{"match_id":"1962068","lobby_id":null,"game_type":1},
{"match_id":"1962821","lobby_id":null,"game_type":0},
{"match_id":"1963814","lobby_id":null,"game_type":0},
{"match_id":"1963807","lobby_id":null,"game_type":0},
{"match_id":"1963908","lobby_id":null,"game_type":0},
{"match_id":"1963716","lobby_id":null,"game_type":0},
{"match_id":"1964491","lobby_id":null,"game_type":0},
{"match_id":"1964535","lobby_id":null,"game_type":12},];
for(var i = 0; i < json.length; i++) {
var obj = json[i];
if(obj.game_type==12){
//do something with game_type 12 json object
console.log(obj);
}
}
</script>

javascript extension error: Cannot perform modifications

I'm building a custom dynamicValue extension for paw. However i'm not able to set header in the evaluate method. See the sample code below:
evaluate(context) {
const request = context.getCurrentRequest();
request.setHeader('Content-Type', this.contentType); // <-- this gives warning
return this.createSignable(request); // This returns a base64 string.
}
I get the warning saying Javascript extension error: Cannot perform modifications and the header is not set. ( when i comment out request.setHeader call, i get no warnings)
Can anyone please help me resolve this issue?
This is correct, you cannot use setters (set any value) in a dynamic value. In fact, the way Paw evaluates dynamic values is asynchronous and as multiple evaluations can take place simultaneously it would be impossible to record the modifications. For this reason, Paw is simply denying changes and no change is persisted during evaluation.
In the documentation, it's specified that these methods (like setHeaders) is only available for importer extensions. Sorry for the inconvenience!
I think to achieve what you're trying to do, you would need two dynamic values one set in the Authorization header and one set in the Content-Type header.
Alternatively, in the future we're going to add request post-processors, so you'll be able to mutate the computed request ready to be sent to the server for additional modifications.

how to create this nonce?

I need a bit of help understanding what this means:
https://wordpress.org/plugins/json-api/other_notes/#Method:-create_post
Required argument
nonce - available from the get_nonce method (call with vars controller=posts >and method=create_post)
How should I create that nonce?
I'm trying:
wp_nonce_field( 'posts', 'create_post' );
Note that you don't have to use the wordpress nonce functionality directly, instead use Json Api's given method in the post controller.
You may try the solution of bbottema
First you need a nonce (Number used ONCE), which is a temporary key you'll use to be able to invoke the API with:
http://yourblog.com/?json=core.get_nonce&controller=posts&method=create_post&callback=?
This gives you a nonce number (be sure to use &callback=? as it marks the content as jsonp, or you'll get a similar -but invalid- nonce).
Then use this nonce to create a post:
http://yourblog.com/?json=posts.create_post&nonce='+nonce+'&title='+title+'&content='+content+'&status=publish (or draft, or leave it out altogether)
Make sure you have the 'posts' controller enabled in your wordpress plugin JSon API settings. Check this manual for what JSon data structures you can expect back from these calls.
Now, here's the tricky part: you need to be already logged into the wordpress site, because with this JSon API, you can't log in. I haven't figured that part out yet, so I'm still looking for a good solution myself. I tried manually posting and also width ajax but with limited results considering I'm missing a WordPress test cookie in my headers (at least this is the main difference I see when logging in from the site and doing it manually)
JSON API USER Does not work, it will only work if you are logged in to the website with an account of ADMIN ROLE!.. otherwise it won't create valid nonce

What wp_verify_nonce() means?

I've read the reference of this function on Wordpress but i still don't understand what this function really does.
I'm reading a tutorial about creating a meta box in wordpress and I have this code inside the function which saves the data:
if ( !wp_verify_nonce( $_POST[$meta_box['name'].'_noncename'], plugin_basename(__FILE__) )) {
return $post_id;
}
Can someone explain briefly what is the meaning of wp_verify_nonce() ?
The nonce is a 'number used once' - a code that WP uses to make sure that POST data is coming from a safe place. This is useful to make sure that your plugin does not end up digesting data from an unsafe source (see Cross-Site Request Forgery).
This blog post by Mark Jaquith is useful for understanding them.
[nonces] are unique to the WordPress install, to the WordPress user, to the action, to the object of the action, and to the time of the action (24 hour window). That means that if any of these things changes, the nonce is invalid. So if you (somehow) intercept a nonce being used by me, you would, first of all, only have 24 hours to use this key to attempt to trick me.
To create a nonce you must give wp_create_nonce a certain string, providing the 'context' for the nonce. It gives you back a string - the nonce itself. You then include this nonce as part of your POST request. The receiving page should then create a nonce of its own, using the same context, and see if they match up.
In this case, the context given is plugin_basename(__FILE__). This will generate the same string whenever it is called from within the same plugin (see here).
When your wp_verify_nonce recieves a nonce created under the same circumstances as specified by Mark, with the same context string, it returns true.
In short:
!wp_verify_nonce
returns true if wp_verify_nonce returns false.
($_POST[$meta_box['name'].'_noncename'],
First argument to wp_verify_nonce: the nonce to check. This code gets the nonce out of the post request, stored in the $_POST global.
plugin_basename(__FILE__) )
Second argument to wp_verify_nonce: the context for generating the new nonce against which the first will be checked.
{ return $post_id; }
If the nonce doesn't match, stop executing the current function, returning the variable $post_id.

Is it considered bad practice to perform HTTP POST without entity body?

I need to invoke a process which doesn't require any input from the user, just a trigger. I plan to use POST /uri without a body to trigger the process. I want to know if this is considered bad from both HTTP and REST perspectives?
I asked this question on the IETF HTTP working group a few months ago. The short answer is: NO, it's not a bad practice (but I suggest reading the thread for more details).
Using a POST instead of a GET is perfectly reasonable, since it also instructs the server (and gateways along the way) not to return a cached response.
POST is completely OK. In difference of GET with POST you are changing the state of the system (most likely your trigger is "doing" something and changing data).
I used POST already without payload and it "feels" OK. One thing you should do when using POST without payload: Pass header Content-Length: 0. I remember problems with some proxies when I api-client didn't pass it.
If you use POST /uri without a body it is something like using a function which does not take an argument .e.g int post (void); so it is reasonable to have function to your resource class which can change the state of an object without having an argument. If you consider to implement the Unix touch function for a URI, is not it be good choice?
Yes, it's OK to send a POST request without a body and instead use query string parameters. But be careful if your parameters contain characters that are not HTTP valid you will have to encode them.
For example if you need to POST 'hello world' to and end point you would have to make it look like this: http://api.com?param=hello%20world
Support for the answers that POST is OK in this case is that in Python's case, the OpenAPI framework "FastAPI" generates a Swagger GUI (see image) that doesn't contain a Body section when a method (see example below) doesn't have a parameter to accept a body.
the method "post_disable_db" just accepts a path parameter "db_name" and doesn't have a 2nd parameter which would imply a mandatory body.
#router.post('/{db_name}/disable',
status_code=HTTP_200_OK,
response_model=ResponseSuccess,
summary='',
description=''
)
async def post_disable_db(db_name: str):
try:
response: ResponseSuccess = Handlers.databases_handler.post_change_db_enabled_state(db_name, False)
except HTTPException as e:
raise (e)
except Exception as e:
logger.exception(f'Changing state of DB to enabled=False failed due to: {e.__repr__()}')
raise HTTPException(HTTP_500_INTERNAL_SERVER_ERROR, detail=e.__repr__())
return response

Resources