ZF3 development of RestAPI: handling Post request for - zend-framework3

I am new to Zf3, and developing Email Restful API.
having difficulties in handling request. I can't get POST parameters.i think there is some problem in module.config.php > 'router'
Questions
1 How can I get POST variables from request.
2 I found it when I request page (using Postman)
- if I passes ID, controller call get($id) method
- if I POST variables controller calls Create($data) function.
--is this always the case ? and is it good to write zendEmail code inside create($data) method
.
bwsmail controller
(create function)
public function create($data)
{
echo $this->getRequest()->getPost('id', "no value");
// Output
// this returns no value
echo $this->getRequest();
// Output
//POST http://localhost:8080/bwsmail/mail?id=123456789 HTTP/1.1
//Cookie: PHPSESSID=p5i7o8lm2ed0iocdhkc8jvos01
//Cache-Control: no-cache
//Postman-Token: ccaf5b37-02a2-4537-bf3f-c1dc419d8ceb
//User-Agent: PostmanRuntime/7.6.1
//Accept: */*
//Host: localhost:8080
//Accept-Encoding: gzip, deflate
//Content-Length: 0
//Connection: keep-alive
$response = $this->getResponseWithHeader()->setContent( __METHOD__.' create new item of data :<b>'.'</b>');
return $response;
}
module.config.php (route)
'bwsmail' => [
'type' => Literal::class,
'options' => [
'route' => '/bwsmail',
'defaults' => [
'controller' => Controller\BwsMailController::class,
]
],
'may_terminate' => true,
'child_routes' => [
'mail' => [
'type' => 'segment',
'options' => [
'route' => '/mail[/:id]',
'constraints'=>
[
'id' => '[0-9a-zA-Z]+',
],
'defaults' => [
'controller' => Controller\BwsMailController::class,
]
],
],
],
],

if BwsMailController extends AbstractController or AbstractRestfulController you can simply: $this->params()->fromRoute() or ->fromQuery() if you're using a get string. For example:
$routeParamId = $this->params()->fromRoute('id', null);
This gets the parameter id as it is defined in the route configuration. If it's not set, it will default to null.
If you have a GET url, something like: site.com/mail?id=123, then you do:
$getParamId = $this->params()->fromQuery('id', null); // sets '123' in var
More options are available, have a good read of the routing documentation.

Related

How can I Unit Test GraphQL file Upload with API Platform?

In addition to my other tests against my GraphQL API Platform backend, I am attempting to test file uploads. I'm not quite sure whether the ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client class has the ability to facilitate this test, or if Symfony\Component\HttpFoundation\File\UploadedFile should be used to provide the test file as it is for a REST operation.
Here is roughly where I am at in terms of putting together this test. (With some irrelevant parts removed for simplification)
public function testCreateMediaObject(): void {
$file = new UploadedFile('fixtures/files/logo.png', 'logo.png');
$client = self::createClient();
$gql = <<<GQL
mutation UploadMediaObject(\$file: Upload!) {
uploadMediaObject(input: {file: \$file}) {
mediaObject {
id
contentUrl
}
}
}
GQL;
$response = $client->request('POST', '/api/graphql', [
'headers' => ['Content-Type' => 'application/json'],
'json' => [
'query' => $gql,
'variables' => ["file" => null],
'map' => ['0' => ['variables.file']],
'0' => $file,
]
]);
dd($response);
}
The response I get seems to indicate that the file isn't being included as expected. Something like...
Variable "$file" of non-null type "Upload!" must not be null.
Or.. if I try to attach the file by simply assigning it directly in the variables property...
$response = $client->request('POST', '/api/graphql', [
'headers' => ['Content-Type' => 'application/json'],
'json' => [
'query' => $gql,
'variables' => ["file" => $file],
]
]);
then...
Variable "$file" got invalid value []; Expected type Upload; Could not get uploaded file, be sure to conform to GraphQL multipart request specification. Instead got: []
In my most recent attempt, I changed things up quite a bit after sifting through the graphql code...
$formFields = [
'operations' => '{ "query": "mutation ($file: Upload!) { uploadMediaObject(input: {file: $file}) { mediaObject { id contentUrl } } }", "variables": { "file": null } }',
'map' => "{'0': ['variables.file']}",
'0' => DataPart::fromPath(__DIR__.'/../../fixtures/files/logo.png'),
];
$formData = new FormDataPart($formFields);
$response = $client->request('POST', '/api/graphql', [
'headers' => $formData->getPreparedHeaders()->toArray(),
'body' => $formData->bodyToString(),
]);
The problem with this last attempt is that the server isn't seeing any body parameters. So I receiving the exception
'GraphQL multipart request does not respect the specification.'
Which is found in /api-platform/core/src/GraphQl/Action/EntrypointAction.php within the parseMultipartRequest method.
After a few hours of debugging I found this solution:
$formData = new FormDataPart();
$file = new UploadedFile('src/DataFixtures/files/test.txt', 'test.txt');
$response = $this->$client->request('POST', 'api/graphql', [
'headers' => $formData->getPreparedHeaders()->toArray(),
'extra' => [
'parameters' => [
'operations' => '{ "query": "mutation UploadMediaObject($file: Upload!) { uploadMediaObject(input: {file: $file}) { mediaObject { id contentUrl } } }", "variables": { "file": null } }',
'map' => '{ "0": ["variables.file"] }',
'0' => #$file,
],
'files' => [
$file,
],
],
]);
Refrence:
https://github.com/jaydenseric/graphql-multipart-request-spec
https://api-platform.com/docs/core/graphql/

HTTP/2 400 returned for URL when using symfoy HTTP Client to make post request

I want to transform a http post request tested with post man to symfony action :
I want to transform the payload to a json array in symfony to send data to url :
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\Routing\Annotation\Route;
class PushNotificationController extends AbstractController
{
/**
* #Route("/api/push_notification", name="push_notification")
*/
public function index()
{
$httpClient = HttpClient::create();
$response = $httpClient->request('POST', 'https://fcm.googleapis.com/fcm/send', [
'headers' => [
// 'Accept' => 'application/json',
// "Content-Type" => "application/json; charset=UTF-8",
'Authorization' => 'Bearer token'
],
'json' => [
'notification' => [
'title' => 'Portugal vs. Denmark',
'message' => 'My Notification Message',
'body' => '5 to 1',
],
'token' => 'token'
],
]);
$statusCode = $response->getStatusCode();
// $statusCode = 200
$contentType = $response->getHeaders()['content-type'][0];
// $contentType = 'application/json'
$content = $response->getContent();
// $content = '{"id":521583, "name":"symfony-docs", ...}'
$content = $response->toArray();
// $content = ['id' => 521583, 'name' => 'symfony-docs', ...]
return $content;
}
}
I got this error :
I think it's an error about the payload . any suggestions please ?
Error 400 Invalid Json input:
Only applies for JSON requests. Indicates that the request could not
be parsed as JSON, or it contained invalid fields (for instance,
passing a string where a number was expected). The exact failure
reason is described in the response and the problem should be
addressed before the request can be retried.
so i guess you need to review your json that you sent.
also , you can use some of the FCM Bundle from Knp or git.

Cakephp 3 - Query Fixture in IntegrationTestTrait

I am having issues querying a loaded Fixture in my TestCase for an IntegrationTestTrait. I want to verify that a record already exist inside of a Fixture, then insert a duplicate record and verify that there is still only 1 record in the database.
During my test case initialization, I set the session variable for authentication.
public function setUp() {
parent::setUp();
$this->loadFixtures(
'Students', 'Users');
// Configure Authentication
$this->session([
'Auth' => [
'User' => [
'id' => 21896,
'institution_id' => 1,
'student_id' => null,
'contact_id' => 91,
'email' => 'AuthenticatedEmail#school.edu',
'role' => 'DSP',
'is_admin' => false
]
]
]);
// Load Tables
$this->Students = TableRegistry::getTableLocator()->get('Students');
}
In my Test Case, I check to see if the Database contains a record, then submit a POST request then test to see if the record did not insert.
public function testAddStudentSuccess() {
$data = [
'institution_id' => 1,
'contact_id' => null,
'id_number' => '200XYZ',
'last_name' => 'Trimor',
'first_name' => 'Paul',
'email' => '1_test#email.com'
];
// Test Pre-condition
$query = $this->Students->find('all')->where([
'id_number' => $data['id_number']
]);
$this->assertEquals(1, $query->count());
$this->post('students/add', $data);
// Test Post-condition
$this->assertResponseSuccess();
$query = $this->Students->find('all')->where([
'id_number' => $data['id_number']
]);
$this->assertEquals(1, $query->count());
}
However, when I run the Test Case, I get the following error:
Notice Error: Undefined variable: _SESSION in/var/www/html/samusg/src/Model/Table/StudentsTable.php, line 206]
A couple things:
The last assertion works! After $this->post('students/add', $data) is submitted, the $query is populated with data.
The first assertion does not work. I debug the Fixture before the $this->post() is called and it returns empty.
In the Test Table, there is a test for $_SESSION variable, which is what line 206 referring to.
Long Story short: The Fixture is not populated with data during the start of the Test Case, but once the integration runs then the Fixture magically contains all the data. I get $_SESSION errors, but I already set the session in the setUp(), so I'm lost.
I greatly appreciate any help. Thank you
I was able to by pass this message by setting the $_SESSION super global directly on my Test:
public function setUp() {
parent::setUp();
$this->loadFixtures(
'Students', 'Users');
// Configure Authentication
$this->session([
'Auth' => [
'User' => [
'id' => 21896,
'institution_id' => 1,
'student_id' => null,
'contact_id' => 91,
'email' => 'AuthenticatedEmail#school.edu',
'role' => 'DSP',
'is_admin' => false
]
]
]);
$_SESSION = [
'Auth' => [
'User' => [
'id' => 21896,
'institution_id' => 1,
'student_id' => null,
'contact_id' => 91,
'email' => 'AuthenticatedEmail#school.edu',
'role' => 'DSP',
'is_admin' => false
]
]
];

How to store and log for all http request and response in wordpress?

I want to store all outgoing http request from my wordpress site. I want to store all internal and external http request and response also request made with curl. Any help should be useful to me.
Hook into WP_Http::_dispatch_request()
function fn_log_http_request_response( $wp_http_response, $request, $url ) {
$request = [
'method' => $request['method'],
'url' => $url,
'headers' => $request['headers'],
'body' => $request['body'],
];
if($wp_http_response instanceof WP_Error) {
$response = [
'errors' => $wp_http_response->errors,
'error_data' => $wp_http_response->error_data,
];
} else {
$response = [
'status' => [
'code' => wp_remote_retrieve_response_code($wp_http_response),
'message' => wp_remote_retrieve_response_message($wp_http_response),
],
'headers' => wp_remote_retrieve_headers($wp_http_response)->getAll(),
'body' => wp_remote_retrieve_body($wp_http_response),
];
}
error_log(print_r([
'request' => $request,
'response' => $response,
], true));
return $wp_http_response;
}
// hook into WP_Http::_dispatch_request()
add_filter('http_response', 'fn_log_http_request_response', 10, 3 );
Adopted from hinnerk-a
You can also try the following plugin as well
https://wordpress.org/plugins/log-http-requests

Getting Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException

I'm sending a PUT request that handles input data and updates a record, but I get the above response. The problem doesn't seem to be the route, however, because if I do dd($user) after the $user = User::whereId($id)->firstOrFail(); line, I get the object returned correctly.
Yet, when it comes time to validate it, it throws this error.
# routes
Route::resource('users', 'UsersController', ['only' => ['index', 'show', 'update']]);
# api call
PUT /users/2
# controller
public function update($id)
{
$user = User::whereId($id)->firstOrFail();
$input = Input::all();
$this->userForm->validate($input);
$user->fill($input)->save();
return $user->toJson();
}
# userForm class
<?php namespace Olp\Forms;
use Laracasts\Validation\FormValidator;
class UserForm extends FormValidator {
protected $rules = [
'email' => 'required|email|unique:users',
'password' => 'required',
'password_confirmation' => 'required|same:password',
'firstname' => 'required',
'lastname' => 'required',
'schoolname' => 'required',
'address1' => 'required',
'address2' => 'required',
'postcode' => 'required',
'city' => 'required'
];
}
and in my UserController:
use Olp\Forms\UserForm;
class UsersController extends \BaseController {
function __construct(UserForm $userForm)
{
$this->userForm = $userForm;
}
I'm not a Laravel guy, but a quick check on their documentation indicates that Resource Controllers support PUT in addition to other HTTP verbs.
I was not able to figure out how to add HTTP verb support to an arbitrary action, but this indicates that you can name a controller action prefixed with the verb it responds to
public function putUpdate($id)

Resources