8000 feature #28919 [DX][WebProfilerBundle] Add Pretty Print functionality… · symfony/http-kernel@e2a7971 · GitHub
[go: up one dir, main page]

Skip to content

Commit e2a7971

Browse files
committed
feature #28919 [DX][WebProfilerBundle] Add Pretty Print functionality for Request Content (SamFleming)
This PR was squashed before being merged into the 4.3-dev branch (closes #28919). Discussion ---------- [DX][WebProfilerBundle] Add Pretty Print functionality for Request Content | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | n/a ? ## Why? Quite often when attempting to debug issues with JSON requests sent to a Symfony API, I use the Web Profiler to check the request content. More often than not the request content isn't easily readable (99% of the time it's all stuck on a single line and impossible to read). I always find myself copying + pasting the content into a random online tool to have it "pretty-print" the JSON. Usually this isn't an issue, but can be annoying when offline. There's also the security issue of sending entire JSON payloads to a third-party server just for formatting 😳. Alternatively, maybe developers copy+paste into their chosen editors and this PR is all a waste of time — I hope not 😛. ## How? This PR adds "Pretty-Print" JSON functionality straight into the profiler. We can use `collector.requestheaders` to detect if the request was JSON and conditionally show the Pretty Print button. When the button is clicked, we format the JSON from the "Request Content" card. ## What does it look like? Before: ![without-pretty-print](https://user-images.githubusercontent.com/573318/47180751-36b0ce00-d319-11e8-86ed-eb0d78ebcbe3.png) After: ![pretty](https://user-images.githubusercontent.com/573318/47180763-3c0e1880-d319-11e8-995d-eba565aad827.png) Non-JSON Requests (unchanged): ![non-json-request](https://user-images.githubusercontent.com/573318/47181080-03227380-d31a-11e8-8cf2-e8b2e8c1a21d.png) ## Things to consider - Is `JSON.stringify(JSON.parse(content));` the safest, most efficient way to do this? - Should the "Pretty Print" button be in-line next to the "Request Content" header? I couldn't find a pattern for this sort of thing elsewhere in the profiler. - Do people want JSON formatted with 4 spaces, would 2 spaces be preferred? Should this be a configuration option stored in localStorage (such as the light/dark theme configuration)? - Should this be a toggle? E.g. click to pretty print, then click to undo ## Future Improvements Depending on how this is received it could be extended to support formatting different request content-types (e.g. XML formatting) — I assume. ## Progress - [x] Gather feedback and decide where to perform the pretty-print: [server-side, or client-side](symfony/symfony#28919 (comment)). *It was decided server-side would be better.* Commits ------- 9f85103 [DX][WebProfilerBundle] Add Pretty Print functionality for Request Content
2 parents 9a234e3 + 0c492d9 commit e2a7971

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

DataCollector/RequestDataCollector.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,18 @@ public function getContent()
252252
return $this->data['content'];
253253
}
254254

255+
public function isJsonRequest()
256+
{
257+
return 1 === preg_match('{^application/(?:\w+\++)*json$}i', $this->data['request_headers']['content-type']);
258+
}
259+
260+
public function getPrettyJson()
261+
{
262+
$decoded = json_decode($this->getContent());
263+
264+
return JSON_ERROR_NONE === json_last_error() ? json_encode($decoded, JSON_PRETTY_PRINT) : null;
265+
}
266+
255267
public function getContentType()
256268
{
257269
return $this->data['content_type'];

Tests/DataCollector/RequestDataCollectorTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,4 +333,58 @@ private function getCookieByName(Response $response, $name)
333333

334334
throw new \InvalidArgumentException(sprintf('Cookie named "%s" is not in response', $name));
335335
}
336+
337+
/**
338+
* @dataProvider provideJsonContentTypes
339+
*/
340+
public function testIsJson($contentType, $expected)
341+
{
342+
$response = $this->createResponse();
343+
$request = $this->createRequest();
344+
$request->headers->set('Content-Type', $contentType);
345+
346+
$c = new RequestDataCollector();
347+
$c->collect($request, $response);
348+
349+
$this->assertSame($expected, $c->isJsonRequest());
350+
}
351+
352+
public function provideJsonContentTypes()
353+
{
354+
return array(
355+
array('text/csv', false),
356+
array('application/json', true),
357+
array('application/JSON', true),
358+
array('application/hal+json', true),
359+
array('application/xml+json', true),
360+
array('application/xml', false),
361+
array('', false),
362+
);
363+
}
364+
365+
/**
366+
* @dataProvider providePrettyJson
367+
*/
368+
public function testGetPrettyJsonValidity($content, $expected)
369+
{
370+
$response = $this->createResponse();
371+
$request = Request::create('/', 'POST', array(), array(), array(), array(), $content);
372+
373+
$c = new RequestDataCollector();
374+
$c->collect($request, $response);
375+
376+
$this->assertSame($expected, $c->getPrettyJson());
377+
}
378+
379+
public function providePrettyJson()
380+
{
381+
return array(
382+
array('null', 'null'),
383+
array('{ "foo": "bar" }', '{
384+
"foo": "bar"
385+
}'),
386+
array('{ "abc" }', null),
387+
array('', null),
388+
);
389+
}
336390
}

0 commit comments

Comments
 (0)
0