Skip to content

Commit 5421575

Browse files
authored
Merge pull request #96 from bystro/SendRequestAsHTMLformVer2.0
Sending POST request as HTML form
2 parents 3463bcc + 28397bb commit 5421575

File tree

6 files changed

+162
-83
lines changed

6 files changed

+162
-83
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Feature: Test request to API sent like a HTML form
2+
In order to test my API
3+
As a developper
4+
I want to be able to perform HTTP request with HTML form data
5+
6+
Scenario: Sending POST request as a HTML form
7+
When I send a POST request to "post-html-form" as HTML form with body:
8+
| object | name | value |
9+
| field | username | pablo |
10+
| field | password | money |
11+
| field | terms_accepted | 1 |
12+
Then the response status code should be 200
13+
And the response should be in JSON
14+
And the JSON node "content_type_header_value" should contain "application/x-www-form-urlencoded"
15+
And the JSON node "post_fields_count" should be equal to "3"
16+
And the JSON node "post_fields.username" should be equal to "pablo"
17+
And the JSON node "post_fields.password" should be equal to "money"
18+
And the JSON node "post_fields.terms_accepted" should be equal to "1"
19+
20+
Scenario: Sending POST request as a HTML form with files
21+
When I send a POST request to "post-html-form-with-files" as HTML form with body:
22+
| object | name | value |
23+
| field | username | pablo |
24+
| field | password | money |
25+
| field | terms_accepted | 1 |
26+
| file | test-img | features/bootstrap/fixtures/test-img.jpg |
27+
| file | json-schema | features/bootstrap/fixtures/json-schema.json |
28+
Then the response status code should be 200
29+
And the response should be in JSON
30+
And the JSON node "content_type_header_value" should contain "multipart/form-data"
31+
And the JSON node "post_fields_count" should be equal to "3"
32+
And the JSON node "post_files_count" should be equal to "2"
33+
And the JSON node "post_fields.username" should be equal to "pablo"
34+
And the JSON node "post_fields.password" should be equal to "money"
35+
And the JSON node "post_fields.terms_accepted" should be equal to "1"

features/send_request.feature

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,4 @@ Feature: Test send API request
4040
Then the response status code should be 200
4141
And the JSON node "headers.header" should have 1 element
4242
And the JSON node "headers.header[0]" should be equal to "value2"
43-
44-
Scenario: Attaching files and sending POST request
45-
Given I add "Content-type" header equal to "application/json"
46-
And I attach the following files:
47-
| name | path |
48-
| json-schema | features/bootstrap/fixtures/json-schema.json |
49-
| test-img | features/bootstrap/fixtures/test-img.jpg |
50-
When I send a POST request to "post-with-files" with parameters:
51-
| username | pablo |
52-
| password | money |
53-
| terms_accepted | 1 |
54-
Then the response status code should be 200
55-
And the response should be in JSON
56-
And the JSON node "post_files_count" should be equal to "2"
57-
And the JSON node "post_fields.username" should be equal to "pablo"
58-
And the JSON node "post_fields.password" should be equal to "money"
59-
And the JSON node "post_fields.terms_accepted" should be equal to "1"
60-
And the JSON node "content_type_header_value" should not contain "application/json"
61-
And the JSON node "content_type_header_value" should contain "multipart/form-data"
43+

src/Html/Form.php

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
namespace Ubirak\RestApiBehatExtension\Html;
4+
5+
class Form
6+
{
7+
private $body = [];
8+
9+
private $contentTypeHeaderValue = '';
10+
11+
public function __construct(array $body)
12+
{
13+
$this->body = $body;
14+
}
15+
16+
public function getBody()
17+
{
18+
if ($this->bodyHasFileObject()) {
19+
return $this->getMultipartStreamBody();
20+
}
21+
22+
return $this->getNameValuePairBody();
23+
}
24+
25+
/**
26+
*
27+
* @return string
28+
*/
29+
public function getContentTypeHeaderValue()
30+
{
31+
return $this->contentTypeHeaderValue;
32+
}
33+
34+
/**
35+
*
36+
* @param string $value
37+
*/
38+
private function setContentTypeHeaderValue($value)
39+
{
40+
$this->contentTypeHeaderValue = $value;
41+
}
42+
43+
/**
44+
*
45+
* @return boolean
46+
*/
47+
private function bodyHasFileObject()
48+
{
49+
foreach ($this->body as $element) {
50+
if ($element['object'] == 'file') {
51+
return true;
52+
}
53+
}
54+
55+
return false;
56+
}
57+
58+
/**
59+
*
60+
* @return \GuzzleHttp\Psr7\MultipartStream
61+
*/
62+
private function getMultipartStreamBody()
63+
{
64+
$multiparts = array_map(
65+
function ($element) {
66+
67+
if ($element['object'] == 'file') {
68+
return ['name' => $element['name'], 'contents' => fopen($element['value'], 'r')];
69+
}
70+
71+
return ['name' => $element['name'], 'contents' => $element['value']];
72+
}, $this->body
73+
);
74+
75+
$boundary = sha1(uniqid('', true));
76+
77+
$this->setContentTypeHeaderValue('multipart/form-data; boundary=' . $boundary);
78+
79+
return new \GuzzleHttp\Psr7\MultipartStream($multiparts, $boundary);
80+
}
81+
82+
/**
83+
*
84+
* @return string
85+
*/
86+
private function getNameValuePairBody()
87+
{
88+
$body = [];
89+
foreach ($this->body as $element) {
90+
$body[$element['name']] = $element['value'];
91+
}
92+
93+
$this->setContentTypeHeaderValue('application/x-www-form-urlencoded');
94+
95+
return http_build_query($body, null, '&');
96+
}
97+
98+
}

src/Rest/RestApiBrowser.php

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ class RestApiBrowser
2727
/** @var array */
2828
private $requestHeaders = [];
2929

30-
/** @var array */
31-
private $requestFiles = [];
32-
3330
/** @var ResponseStorage */
3431
private $responseStorage;
3532

@@ -103,7 +100,9 @@ public function sendRequest($method, $uri, $body = null)
103100
}
104101

105102
if (is_array($body)) {
106-
$body = $this->buildMultipartBody($body);
103+
$html = new \Ubirak\RestApiBehatExtension\Html\Form($body);
104+
$body = $html->getBody();
105+
$this->setRequestHeader('Content-Type', $html->getContentTypeHeaderValue());
107106
}
108107

109108
$this->request = $this->messageFactory->createRequest($method, $uri, $this->requestHeaders, $body);
@@ -164,47 +163,6 @@ private function removeRequestHeader($headerName)
164163
}
165164
}
166165

167-
/**
168-
* @param string $name
169-
* @param string $path
170-
*/
171-
public function addFileToRequest($name, $path)
172-
{
173-
$this->requestFiles[] = [
174-
'name' => $name,
175-
'path' => $path,
176-
];
177-
}
178-
179-
/**
180-
* @param array $body
181-
*
182-
* @return \GuzzleHttp\Psr7\MultipartStream
183-
*/
184-
private function buildMultipartBody($body)
185-
{
186-
$multiparts = array_merge(
187-
array_map(
188-
function ($key, $value) {
189-
return ['name' => $key, 'contents' => $value];
190-
},
191-
array_keys($body),
192-
$body
193-
),
194-
array_map(
195-
function ($file) {
196-
return ['name' => $file['name'], 'contents' => fopen($file['path'], 'r')];
197-
},
198-
$this->requestFiles
199-
)
200-
);
201-
202-
$boundary = sha1(uniqid('', true));
203-
$this->setRequestHeader('Content-Type', 'multipart/form-data; boundary='.$boundary);
204-
205-
return new \GuzzleHttp\Psr7\MultipartStream($multiparts, $boundary);
206-
}
207-
208166
/**
209167
* @param string $uri
210168
*

src/RestApiContext.php

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,27 +48,21 @@ public function iSendARequestWithBody($method, $url, PyStringNode $body)
4848
}
4949

5050
/**
51-
* Sends HTTP request to specific URL with raw body from PyString.
52-
*
53-
* @param string $method request method
54-
* @param string $url relative url
55-
* @param TableNode $parameters
56-
*
57-
* @When /^(?:I )?send a ([A-Z]+) request to "([^"]+)" with parameters:$/
51+
* @When I send a POST request to :url as HTML form with body:
5852
*/
59-
public function iSendARequestWithParameters($method, $url, TableNode $parameters = null)
53+
public function iSendAPostRequestToAsHtmlFormWithBody($url, TableNode $body)
6054
{
61-
$this->restApiBrowser->sendRequest($method, $url, $parameters->getRowsHash());
62-
}
55+
$formElements = [];
56+
foreach ($body as $element) {
6357

64-
/**
65-
* @When I attach the following files:
66-
*/
67-
public function iAttachTheFollowingFiles(TableNode $files)
68-
{
69-
foreach ($files as $file) {
70-
$this->restApiBrowser->addFileToRequest($file['name'], $file['path']);
58+
if (!isset($element['object'])) {
59+
throw new \Exception('You have to specify an object attribute');
60+
}
61+
62+
$formElements[] = $element;
7163
}
64+
65+
$this->restApiBrowser->sendRequest("POST", $url, $formElements);
7266
}
7367

7468
/**

www/index.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,23 @@ function (Request $request) {
6868
);
6969

7070
$app->match(
71-
'post-with-files',
72-
function (Request $request) {
71+
'post-html-form',
72+
function (Request $request) {
73+
return new JsonResponse([
74+
'content_type_header_value' => $request->headers->get('content-type'),
75+
'post_fields_count' => $request->request->count(),
76+
'post_fields' => $request->request->all(),
77+
]);
78+
}
79+
);
80+
81+
$app->match(
82+
'post-html-form-with-files',
83+
function (Request $request) {
7384
return new JsonResponse([
7485
'content_type_header_value' => $request->headers->get('content-type'),
7586
'post_files_count' => count($request->files),
87+
'post_fields_count' => $request->request->count(),
7688
'post_fields' => $request->request->all(),
7789
]);
7890
}

0 commit comments

Comments
 (0)