Skip to content

Commit 11818bc

Browse files
Ricky-rickbarryvdh
authored andcommitted
Option to use debugbar with content-security-policy headers (barryvdh#569)
* Option to use debugbar with content-security-policy headers * Update default value for csp-compatible Users that have don't update the config file will use this default,
1 parent d3cdca2 commit 11818bc

File tree

5 files changed

+98
-0
lines changed

5 files changed

+98
-0
lines changed

config/debugbar.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,17 @@
164164
],
165165
],
166166

167+
/*
168+
|--------------------------------------------------------------------------
169+
| Content security policy compatible
170+
|--------------------------------------------------------------------------
171+
|
172+
| If you have set a content security policy in your header you need to set
173+
| this variable to true. You need to add "img-src:'self' data:" to your
174+
| csp header. Note: Storage needs to be enabled for this to work.
175+
|
176+
*/
177+
'csp-compatible' => false,
167178
/*
168179
|--------------------------------------------------------------------------
169180
| Inject Debugbar in Response

src/Controllers/AssetController.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ public function css()
4444
return $this->cacheResponse($response);
4545
}
4646

47+
public function init()
48+
{
49+
$renderer = $this->debugbar->getJavascriptRenderer();
50+
$content = $renderer->renderInitScript();
51+
$response = new Response(
52+
$content, 200, [
53+
'Content-Type' => 'text/javascript',
54+
]
55+
);
56+
return $this->cacheResponse($response);
57+
}
4758
/**
4859
* Cache the response 1 year (31536000 sec)
4960
*/

src/JavascriptRenderer.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@ protected function getInlineHtml()
7575

7676
return $html;
7777
}
78+
protected function getJsInitializationCode()
79+
{
80+
$js = '';
81+
if ($this->isJqueryNoConflictEnabled()) {
82+
$js .= 'jQuery.noConflict(true);' . "\n";
83+
}
84+
85+
return $js . parent::getJsInitializationCode();
86+
}
87+
7888
/**
7989
* Get the last modified time of any assets.
8090
*
@@ -113,6 +123,24 @@ public function dumpAssetsToString($type)
113123
return $content;
114124
}
115125

126+
/**
127+
* Return the init script as a string
128+
*
129+
* @return string
130+
*/
131+
public function renderInitScript()
132+
{
133+
$openHandlerUrl = route('debugbar.openhandler');
134+
$this->setOpenHandlerUrl($openHandlerUrl);
135+
$content = $this->getJsInitializationCode();
136+
$content .= sprintf(
137+
"%s.loadDataSet($(\"span[data-debugbar-id]\").attr(\"data-debugbar-id\"), \"(ajax)\");\n",
138+
$this->variableName,
139+
$this->openHandlerClass,
140+
json_encode(array("url" => $this->openHandlerUrl))
141+
);
142+
return $content;
143+
}
116144
/**
117145
* Makes a URI relative to another
118146
*

src/LaravelDebugbar.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,12 @@ public function modifyResponse(Request $request, Response $response)
730730
} catch (\Exception $e) {
731731
$app['log']->error('Debugbar exception: ' . $e->getMessage());
732732
}
733+
} elseif ($app['config']->get('debugbar.inject', true) && $app['config']->get('debugbar.csp-compatible', false)) {
734+
try {
735+
$this->injectDebugbarCSP($response);
736+
} catch (\Exception $e) {
737+
$app['log']->error('Debugbar exception: ' . $e->getMessage());
738+
}
733739
} elseif ($app['config']->get('debugbar.inject', true)) {
734740
try {
735741
$this->injectDebugbar($response);
@@ -861,6 +867,43 @@ public function injectDebugbar(Response $response)
861867
$response->headers->remove('Content-Length');
862868
}
863869

870+
public function injectDebugbarCSP(Response $response)
871+
{
872+
if (!$this->app['config']->get('debugbar.storage.enabled')) {
873+
throw new \Exception('Store needs to be enabled for content security policy');
874+
}
875+
//collect and store data
876+
$this->collect();
877+
878+
$content = $response->getContent();
879+
880+
$renderer = $this->getJavascriptRenderer();
881+
if ($this->getStorage()) {
882+
$openHandlerUrl = route('debugbar.openhandler');
883+
$renderer->setOpenHandlerUrl($openHandlerUrl);
884+
}
885+
886+
$initRoute = route('debugbar.assets.init', [
887+
'v' => filemtime(config_path('debugbar.php'))
888+
]);
889+
890+
$initRoute = preg_replace('/\Ahttps?:/', '', $initRoute);
891+
892+
$scriptContent = $renderer->renderHead() .
893+
"<span data-debugbar-id='{$this->getCurrentRequestId()}'></span>
894+
<script type='text/javascript' src='{$initRoute}'></script>";
895+
896+
$pos = strripos($content, '</body>');
897+
if (false !== $pos) {
898+
$content = substr($content, 0, $pos) . $scriptContent . substr($content, $pos);
899+
} else {
900+
$content = $content . $scriptContent;
901+
}
902+
903+
// Update the new content and reset the content length
904+
$response->setContent($content);
905+
$response->headers->remove('Content-Length');
906+
}
864907
/**
865908
* Disable the Debugbar
866909
*/

src/ServiceProvider.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ public function boot()
9494
'as' => 'debugbar.assets.js',
9595
]);
9696

97+
$router->get('assets/init', [
98+
'uses' => 'AssetController@init',
99+
'as' => 'debugbar.assets.init',
100+
]);
101+
97102
$router->delete('cache/{key}/{tags?}', [
98103
'uses' => 'CacheController@delete',
99104
'as' => 'debugbar.cache.delete',

0 commit comments

Comments
 (0)