Firebase REST API - Guzzle PATCH request is deleting data - http

According to the firebase docs, https://www.firebase.com/docs/rest-api.html, it states:
PATCH - Updating Data
You can update specific children at a location without overwriting existing data
with a PATCH request. Named children in the data being written with PATCH will be
written, but omitted children will not be deleted. This is equivalent to the
update( ) function.
curl -X PATCH -d '{"last":"Jones"}' \
https://SampleChat.firebaseIO-demo.com/users/jack/name/.json
A successful request will be indicated by a 200 OK HTTP status code.
The response will contain the data written:
{"last":"Jones"}
Now my understanding of this, is that if I wish to update only parts of a resource, then I can use a PATCH request.
My simplified firebase database is as follows:
"exchange-rates" : {
"eur" : {
"fx" : 1.2,
"currency_symbol" : "€",
"updated_at" : "2014-06-13T22:49:23+0100",
},
"usd" : {
"fx" : 1.6,
"currency_symbol" : "$",
"updated_at" : "2014-06-13T22:49:23+0100",
},
"gbp" : {
"fx" : 1,
"currency_symbol" : "£",
"updated_at" : "2014-06-16T15:43:15+0100",
}
}
However If I omit the currency_symbol and updated_at from the payload in my patch request, then Firebase removes these attributes from the database.
$auth = 'SUPER_SECRET_CODE';
$guzzleClient = new GuzzleHttp\Client();
$url = https://DATABASE.firebaseio.com/.json;
$data['exchange-rates']['gbp']['fx'] = (float) 1;
$data['exchange-rates']['usd']['fx'] = (float) 1.66;
$data['exchange-rates']['eur']['fx'] = (float) 1.22;
$payload =
[
'query' => [ 'auth' => $auth ],
'json' => $data
];
$response = $guzzleClient->patch($url, $payload);
As such, the PATCH request is not working as it should, or I have misunderstood what Firebase should do with this PATCH request - or I am missing something. Any thoughts?
Also, If I wish to add an object to the exchange-rates object, I should be able to do so.
$data['exchange-rates']['chf']['fx'] = 2.13;
$payload =
[
'query' => [ 'auth' => $auth ],
'json' => $data
];
$response = $guzzleClient->patch($url, $payload);
However all this does is just overwrite all the existing exchange-rates, and now I only have 1 exchange rate in the db.

The update/PATCH operations are not recursive. They only observe keys for the direct children of your update. Example:
// assume data: { foo: 'bar', baz: {uno: 1, dos: 2}, zeta: {hello: 'world'} };
curl -X PATCH -d '{"tres": 3}' $URL
// baz is now: {uno: 1, dos: 2, tres: 3}
curl -X PATCH -d '{"foo": "barr", baz: {"tres": 3}}' $URL
// baz is now {tres: 3}
So the update is only one level deep. If one of the child records you provide is an object, it replaces the child at that path rather than trying to merge the two.

Related

Symfony, Monolog and Slack : how can I format notifications?

On a Symfony 3.4 project, I want to send notifications to a Slack channel via Monolog. I use the SlackHandler and it works well but now I want to find a way to format my notification, using Slack's recommendations. Is it possible ?
For now, each key I send is a new field title and each value associated is a field. Can I directly change the content of "Message" ? Can I also hide the "Level" entry ? I try to use 'fields' from $attachment in SlackRecord.php, but no success so far.
Many, many thanks.
Extracts of what I've done so far. My yaml config:
# monolog.yml
reviews:
type: slack
token: '%token%'
channel: "#mychannel"
bot_name: 'My bot'
icon_emoji: :sports_medal:
level: info
channels: [reviews]
include_extra: true
And in my controller :
// ...
$message = [
'a' => $post->getTitle(),
'b' => $ur->getInterventionRating(),
"fields" => [
"title": "Priority",
"value": "High",
"short": false ], ];
$this->container->get('monolog.logger.myChannel')->info("test", $message);

HTTP client Cakephp 3 ignores json body

I'm currently writing a RESTful API in Cakephp 3 whereby I need to test a POST operation through http://host.com/api/pictures. The code for the test:
<?php
namespace App\Test\TestCase\Controller;
use App\Controller\Api\UsersController;
use Cake\TestSuite\IntegrationTestCase;
use Cake\Network\Http\Client;
use Cake\Network\Http\FormData;
class ApiPicturesControllerTest extends IntegrationTestCase{
public $fixtures = [
'app.users',
'app.comments',
'app.albums',
'app.users_albums'
];
public function testAdd(){
// $data = new FormData();
$accessToken ='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjksImV4cCI6MTQ1NzYyOTU3NH0.NnjXWEQCno3PUiwHhnUCBjiknR-NlmT42oPLA5KhuYo';
$http = new Client([
'headers' => ['Authorization' => 'Bearer ' . $accessToken, 'Content-Type' => 'application/json']
]);
$data = [
"album_id" => 1,
"link" => "http://www.google.com",
"description" => "testtesttest",
"favorite" => true
];
$result = $http->post('http://vecto.app/api/pictures/add.json', $data, ['type'=>'json']);
// $this->assertResponseOk();
// debug($result);
}
}
When I try to debug the result I get a 'cannot add or update child row' while I'm sure the responding id does exists
(the fixtures does have the id's too). Additionally, the log indicates that it only tries to insert the create/update rows. Therefore, I'm pretty sure the data is ignored but however I can't find a solution. I already tried different combination of headers like only application/json for Accept, application/json for Content-Type etc. I'm using the CRUD plugin for Cakephp to pass the data to an add function.
Postman output
Furthermore, I tried the Postman Chrome plugin to save the data and that actually does work. Does anyone know what I'm doing wrong in the test?
That's not how the integration test case is ment to be used. You are dispatching an external, real request, which will leave the test environment, while you should use the request dispatching tools that the integration test case supplies, that is
IntegrationTestCase::get()
IntegrationTestCase::post()
IntegrationTestCase::put()
etc...
These methods will dispatch simulated requests that do not leave the test environment, which is crucial for things to work properly, as you want to use test connections, inspect possible exceptions, have access to the used session, etc...
ie, you should do something along the lines of
$accessToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjksImV4cCI6MTQ1NzYyOTU3NH0.NnjXWEQCno3PUiwHhnUCBjiknR-NlmT42oPLA5KhuYo';
$this->configRequest([
'headers' => [
'Authorization' => 'Bearer ' . $accessToken,
'Content-Type' => 'application/json'
]
]);
$data = [
"album_id" => 1,
"link" => "http://www.google.com",
"description" => "testtesttest",
"favorite" => true
];
$this->post('/api/pictures/add.json', json_encode($data));
Note that a content type of application/json will require you to send raw JSON data! If you don't actually need/want to test parsing of raw input, then you could skip that header, and pass the array as data instead.
See also
Cookbook > Testing > Controller Integration Testing
API > \Cake\TestSuite\IntegrationTestCase

You cannot use a route without an url generator

i'm trying to implement the Hateoas with PaginatedRepresentation, like describe in documentation :
see bellow my controller :
$hateoas = HateoasBuilder::create()->build();
$paginatedCollection = new PaginatedRepresentation(
$collection,
$this->generateUrl('getUsers'), // route
array(), // route parameters
1, // page number
2, // limit
11 // total pages
);
return new Response($hateoas->serialize($paginatedCollection, 'json'),
200,
array('Content-Type' => 'application/json'));
but i got this error : You cannot use a route without an url generator
replaced :
$hateoas->serialize($paginatedCollection, 'json')
by
$this->get('serializer')->serialize($paginatedCollection, 'json')

Changing css according to data

I'm doing a widget with dashing.io and I would like to change the jenkins jobs according to the color I receive in my json file (wich I get from the Jenkins API).
ie: The job is complete, I get the color value "blue" from my json file and I want the text to be blue on the "widget jenkins" i my dashboard.
Problem: I don't really know how to get my data from my json file in my coffeescript script. Neither I know how to change the css.
My json file goes like this:
{
"assignedLabels" : [
{
}
],
"mode" : "NORMAL",
"nodeDescription" : "blabla",
"nodeName" : "",
"numExecutors" : blabla,
"description" : blabla,
"jobs" : [
{
"name" : "JOB_NAME",
"url" : "MY_JOB_URL",
"color" : "blue"
}
]
}
Here is my widget code:
require 'net/http'
require 'json'
require 'time'
JENKINS_URI = URI.parse("jenkins_url")
JENKINS_AUTH = {
'name' => 'user',
'password' => 'pwd'
}
def get_json_for_master_jenkins()
http = Net::HTTP.new(JENKINS_URI.host, JENKINS_URI.port)
request = Net::HTTP::Get.new("/jenkins/api/json?pretty=true")
if JENKINS_AUTH['name']
request.basic_auth(JENKINS_AUTH['name'], JENKINS_AUTH['password'])
end
response = http.request(request)
JSON.parse(response.body)
end
# the key of this mapping must be a unique identifier for your job, the according value must be the name that is specified in jenkins
SCHEDULER.every '100s', :first_in => 0 do |job|
thom = get_json_for_master_jenkins()
send_event('master_jobs',
jobs: thom['jobs'][0..4],
colors:thom['jobs']['color']
)
end
Could you guys help me ? I'm really new to this, try to make it simple please.
OK, I think I found the answer.
Jenkins is built on batman.js, and there is a way to interact with the DOM.
I use the provided batman.js attribute data-bind-class like this in my widget HTML:
.blue{
#CSS stuff goes here
}

Firebase - Invalid path: Invalid token in path

I'm using this PHP package, firebase-php, to communicate with the REST API.
I want to do very basic data push:
require_once ('utilities/firebase/firebaseLib.php');
$firebase = new Firebase(<my firebase url>, <my firebase token>);
$data = [
'ip' => "123456789",
'session' => "1234",
'sequence' => "12",
'time' => "159159159",
'event' => "Pause",
'data' => "1"
];
$res = $firebase->push(<my firbase path.json>, $data);
After execution I get this error: { "error" : "Invalid path: Invalid token in path" }
Not sure what this error means, no explanation at the docs...
Will be thankful for any help!
The firebase path in the push method ($res = $firebase->push(my-firebase.firebaseio.com/structure/of/json, $data); should be the relative path to the main firebase url.
So instead of 'my-firebase.firebaseio.com/structure/of/json' it should be just 'structure/of/json'.

Resources