NotionCommotion Posted August 31, 2019 Share Posted August 31, 2019 (edited) I have a class ServerBridge which is used to proxy browser ajax requests received by a web server to another API server. To update a record (or create a record is similar): Browser client makes PUT request to web server. Web server modifies the uri path and passes the body plus headers connection, accept, accept-encoding, accept-language, content-type, content-length only to the API server. The API server does work and returns the location of the resource on itself to the web server. The web server modifies the location header to point to the resource location on itself, and returns all received headers except Date, Server, X-Powered-By, Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers to the browser client. Browser client makes another undesired PUT request to web server. Why is step 5 occurring and how do I prevent it? I don't really mind the browser client making another request to the resource, but it would need to be GET and not PUT. Also, is my white-list headers to forward to api server and black-list headers to return to browser client appropriate? I haven't posted the ServerBridge script (but can if needed), but did include the requests and headers related to the browser client, web server, and api server below. Browser client JavaScript $('.edit-record').simpleEdit('/api/accounts'); jQuery.fn.extend({ simpleEdit: function(url, options) { var dOptions={type: 'text', ajaxOptions: {type: "PUT"}, placement: 'right', send: 'always' }; options=options?options:{}; return this.each(function() { var $t=$(this); var o=Object.assign({ url: url+'/'+$t.closest('tr').data('id'), title: 'Enter '+$t.data('name') }, dOptions, options); $t.editable(o); }); } }); Web-server index.php $c['serverBridge'] = function ($c) { return new \Greenbean\ServerBridge\ServerBridge( new \GuzzleHttp\Client([ 'base_uri' => $c['settings']['server']['scheme'].'://'.$c['settings']['server']['host'], 'headers' => ['X-Secret-Key' => $c['settings']['server']['key']], 'timeout' => 30, 'allow_redirects' => false, ]), new \Greenbean\ServerBridge\SlimHttpClientHandler() ); }; $app->put('/api/accounts/{id:[0-9]+}', function (Request $request, Response $response) { return $this->serverBridge->proxy($request, $response, function(string $path):string{ return substr($path, 4); //Remove "/api" from uri }, function(array $headers):array{ if(!empty($headers['Location'])) { $headers['Location'] = ['/api'.$headers['Location'][0]]; //Add "/api" to redirect header if it exists } return $headers; } ); }); $app->POST('/api/accounts/{id:[0-9]+}', function (Request $request, Response $response) {/*Similar to PUT*/}); <?php class ServerBridge { public function __construct(\GuzzleHttp\Client $httpClient, ?HttpClientHandlerInterface $httpClientHandler=null){ $this->httpClient=$httpClient; $this->httpClientHandler=$httpClientHandler; //Whether to use Slim or Sympony HTTP requests and responses } public function proxy($clientRequest, $clientResponse=null, \Closure $modifyPath=null, \Closure $modifyHeaders=null) { //Accept a Slim or Sympony HTTP request, forward it to API server via cURL, and return the cURL response //$modifyPath will modify REQUEST_URI before sending to API server //$modifyHeaders will modify response headers before sending to calling client return $response; } } API Server index.php $app->put('/accounts/{id:[0-9]+}', function (Request $request, Response $response, $args) { $this->accounts->update($args['id'], $request->getParsedBody()); return $response->withRedirect('/accounts/'.$args['id'], 302); }); $app->post('/accounts', function (Request $request, Response $response) { $account = $this->accounts->create($request->getParsedBody()); return $response->withRedirect('/accounts/'.$account['id'], 302); }); Browser Client Request URL:https://admin.tapmeister.com/api/accounts/1974750116 Request method:PUT Remote address:73.108.50.132:443 Status code:302 Version:HTTP/1.1 Request headers (477 B) Raw headers Accept */* Accept-Encoding gzip, deflate, br Accept-Language en-US,en;q=0.5 Connection keep-alive Content-Length 30 Content-Type application/x-www-form-urlencoded; charset=UTF-8 Cookie PHPSESSID=d11m0k37mf3veaeg0rs350rvkp Host admin.tapmeister.com Referer https://admin.tapmeister.com/ User-Agent Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/68.0 X-Requested-With XMLHttpRequest Response headers (408 B) Cache-Control no-store, no-cache, must-revalidate Connection Keep-Alive, Keep-Alive Content-Length 0 Content-Type text/html; charset=UTF-8 Date Sat, 31 Aug 2019 16:18:47 GMT Expires Thu, 19 Nov 1981 08:52:00 GMT Keep-Alive timeout=5, max=100 Location /api/accounts/1974750116 Pragma no-cache Server Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips X-Powered-By PHP/7.3.9 Web Server PUT admin.tapmeister.com/api/accounts/1974750116 REDIRECT_STATUS: 200 REDIRECT_URL: /api/accounts/1974750116 Request headers Cookie: PHPSESSID=d11m0k37mf3veaeg0rs350rvkp Connection: keep-alive Content-Length: 30 X-Requested-With: XMLHttpRequest Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Referer: https://admin.tapmeister.com/ Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.5 Accept: */* User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0 Host: admin.tapmeister.com Response headers Date: [Sat, 31 Aug 2019 16:18:47 GMT], Server: [Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips], X-Powered-By: [PHP/7.3.9], Location: [/accounts/1974750116], Content-Length: [0], Access-Control-Allow-Origin: [*], Access-Control-Allow-Methods: [GET, POST, PUT, DELETE, OPTIONS], Access-Control-Allow-Headers: [X-Secret-Key, Origin, X-Requested-With, Content-Type, Accept], Keep-Alive: [timeout=5, max=100], Connection: [Keep-Alive], Content-Type: [text/html; charset=UTF-8] API Server PUT api.admin.tapmeister.com/accounts/1974750116 REDIRECT_STATUS: 200 REDIRECT_URL: /accounts/1974750116 Request headers Content-Length: 30 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Connection: keep-alive Host: api.admin.tapmeister.com User-Agent: GuzzleHttp/6.3.3 curl/7.29.0 PHP/7.3.9 X-Secret-Key: secretKey Edited August 31, 2019 by NotionCommotion Quote Link to comment https://forums.phpfreaks.com/topic/309164-return-resource-location-but-dont-follow-with-same-method/ Share on other sites More sharing options...
kicken Posted August 31, 2019 Share Posted August 31, 2019 Your webserver is responding the the browser with a redirect (Status 302) so the browser is trying to follow that redirect. If you're creating a new resource you should be responding with status code 201. If you're updating an existing resource you should respond with status code 200. 1 Quote Link to comment https://forums.phpfreaks.com/topic/309164-return-resource-location-but-dont-follow-with-same-method/#findComment-1569323 Share on other sites More sharing options...
NotionCommotion Posted August 31, 2019 Author Share Posted August 31, 2019 Slim will use 302 by default with withRedirect($url) which is fine, but also returns 302 using withRedirect($url, 200). 201 for create and 204 for update, however, work as desired. Thanks Quote Link to comment https://forums.phpfreaks.com/topic/309164-return-resource-location-but-dont-follow-with-same-method/#findComment-1569324 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.