Why does PHPUnit interfere with setting HTTP headers in this code? - http-headers

I have a function that creates CSV data and lets the user download it in the browser, basically like this:
function f() {
if ($fp = fopen('php://output', 'w')) {
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=\"foo.csv\"");
fputcsv($fp, $someArrayGoesHere);
flush();
fclose($fp);
// debugging, explained below
error_log(print_r(xdebug_get_headers(), true));
}
}
The code works, presenting the user with a download dialog.
Now, I'm trying to write a PHPunit test to confirm that the two HTTP headers get set. Realizing that headers_list() doesn't work in CLI context (php_sapi_name() == 'cli'), I'm using xdebug_get_headers() to retrieve the headers for testing.
Now comes the trouble. The debugging line in my code above, when run on the web, always prints the headers I expect:
Array
(
[0] => X-Content-Type-Options: nosniff
[1] => Content-Type: text/csv
[2] => Content-Disposition: attachment; filename="foo.csv"
)
But when I run this code in phpunit, the PHPUnit_Util_Printer::write function appears to be producing output before my code sets the headers, and prevents them from being set, producing this debug output:
Cannot modify header information - headers already sent by (output started
at /usr/share/pear/PHPUnit/Util/Printer.php:172)
Array
(
[0] => Content-type: text/html
)
This earlier write is not being produced by me, so is there a way around it? How do I test for my CSV-related headers using phpunit?
I've already read the advice given in these questions, but it hasn't helped:
Headers already sent by PHP
PHPUnit - test for expected headers
PHPUnit - Unit Testing with items that need to send headers
Test PHP headers with PHPunit
Setting HTTP headers to be able to run test cases
I also tried using #runInSeparateProcess with the unit test, but the test crashes horribly: ".Unexpected non-MediaWiki exception encountered, of type "Exception", exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in /usr/share/pear/PHPUnit/Util/GlobalState.php:354". (This is a MediaWiki unit test for a custom extension.)

The answer to your literal question "Why does PHPUnit interfere with setting HTTP headers in this code?" is given fairly clearly in the answer to Test PHP headers with PHPunit. PHP's header() will fail with the Cannot modify header information warning if anything has been written to stdout. When running your code via PHPUnit, content has been sent to stdout long before your code under test has been reached.
You noted a separate issue when using the #runInSeparateProcess annotation to fork a clean PHP process for your test:
Unexpected non-MediaWiki exception encountered, of type "Exception", exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in /usr/share/pear/PHPUnit/Util/GlobalState.php:354
By default PHPUnit attempts to backup all of the $GLOBALS data before each test and restore it afterwards. MediaWikiTestCase turns this behavior off but it looks like your extension's tests are not. It seems likely that the configuration for your extension includes a closure and is causing the serialization failure. Adding a #backupGlobals disabled annotation to your PHPUnit_Framework_TestCase class should get you past this problem.

Related

In karate mocking (karate-netty), how can we override request header value?

Objective:
We want few API calls should go to mock-server(https://192.x.x.x:8001) and others should go to an actual downstream application server(https://dev.api.acme.com).
Setup :
On local, mock server is up with standalone jar on port 8001. e.g https://192.x.x.x:8001
In application config file (config.property)downstream system(which need to mock) defined with mockserver IP i.e https://192.x.x.x:8001
Testing scenario and problem:
1.
Scenario: pathMatches('/profile/v1/users/{id}/user')
* karate.proceed('https://dev.api.acme.com')
* def response = read ('findScope.json')
* def responseStatus = 200ˀˀ
* print 'created response is: ' + response
Now, when we hit API request via postman or feature file then it does karate.proceed properly to https://dev.api.acme.com/profile/v1/users/123/user instead of 192.x.x.x. However, in this request, host is referring to https://192.x.x.x:8001 instead of https://dev.api.acme.com which create a problem for us.
How can we override request header in this case? I did try with karate.set and also with header host=https://192.x.x.x:8001 but no luck.
Thanks!
Please see if the 1.0 version works: https://github.com/intuit/karate/wiki/1.0-upgrade-guide
Unfortunately https proxying may not work as mentioned. If you are depending on this, we may need your help (code contribution) to get this working
If the Host header is still not mutable, that also can be considered a feature request, and here also I'd request you to consider contributing code

Onenote API (REST) - PATCH append - "must include a 'commands'" error when Commands is already supplied (?!)

Note: I'm pretty sure nothing's wrong with the PATCH query, I had it working before with 'Content-type':'application/json' and a constructed json file:
[
{
'target':'|TARGET_ID|',
'action':'append',
'content':'|HTML|'
}
]
For the purposes of this, the header supplied (authentication bearer is correct and will be omitted)
'Content-type':'multipart/form-data; Boundary=sectionboundary'
(note: Boundary=sectionboundary is in the same line)
Attempting to pass the following body as a PATCH to
https://www.onenote.com/api/v1.0/pages/|GUID|/content
returns a
"code":"20124","message":"A multi-part PATCH request must include a 'commands' part containing the PATCH action JSON structure." :
--sectionboundary
Content-Disposition: form-data; name="Commands"
Content-Type: application/json
[
{
'target':'|TARGET_ID|',
'action':'append',
'content':'|HTML|'
}
]
--sectionboundary
Content-Disposition: form-data; name="image-part-name"
Content-Type: image/png
|BINARY_IMAGE_DATA|
--sectionboundary--
As you can see, there's a Commands section already. Using smallcaps 'commands' doesn't help, and the correct syntax should be "Commands" as per the OneNote Dev Center documentation.
PS: |TARGET_ID| |HTML| |GUID| and |BINARY_DATA| are replaced with the correct content at runtime. Due to privacy constraints, the fact that you may use a different schema than I do, and how long |BINARY_IMAGE_DATA| actually is, I will not show the actual input unless required to solve the problem.
Would like to know if I missed anything - thanks in advance.
PPS: Yes, I realize i've omitted the img tag inside |HTML| somewhere. It shouldn't have anything to do with code 20124, and if I got it wrong should return another thing entirely.
Based on investigating the request information you shared, I can confirm that the PATCH request referenced as part of the correlation you provided does not match your posted header information.
The correlated PATCH request shows up as a multi-part request with only a single part that has Media Type "TEXT/HTML" and not "Application/JSON". Can you please check and confirm your request content ?
Let us continue to discuss this on email. If you still face issues calling the API, please write to me at machandw#microsoft.com
Regards,
Manoj

Cannot modify header information - headers already sent by (output [duplicate]

This question already has answers here:
How to fix "Headers already sent" error in PHP
(11 answers)
Closed 8 years ago.
I think I screwed up my website, this is an error I get on one of the pages
Warning : Cannot modify header information - headers already sent by (output started at /home/content/94/9066***/html/websites/{website name}.com/index.php:3) in /home/content/94/9066***/html/websites/{website name}.com/wp-includes/pluggable.php on line 896
How do I get rid of this? Thank you so much for your help!!
You get this error because you're setting a header (most likely with the header function) after some output (body) have already been sent to the client, for example with a echo
The line of code + source file where the body output starts and where you attemp to set a header are in the error you receive.
The rule is first all headers are set then comes the body of the response.
Or just because a line end... Check
<?php // is there a blank line before this one?
...
?> //same question
Usually this warning is thrown when an output (even a space or a blank line) is sent to the browser before the session function call.
As this is happening on a wordpress site, did you modify any code in index.php?
Check if anything is echoed before the session_start() function call.
If we have a little knowledge about HTTP headers, we can fix "Headers already sent" errors. So I will touch just the overview of headers.
During a HTTP request, HTTP headers called [REQUEST HEADERS] are sent from client to the server and during a HTTP response, HTTP headers called [RESPONSE HEADERS] are sent from server to client.
Now, what the hell these headers contain?
REQUEST HEADERS--> Hostname,cookie info, the kind of encoding that the client accepts,etc.
RESPONSE HEADERS--> Content type being sent, info about Content encoding, etc.
You can get a lot of info about the headers in the below link:
http://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039
In plain English, Headers contain information about the page being requested or sent.
Now Answering the ques:
Php header() function modifies the default RESPONSE headers and includes information that you want to send.
THUMBRULE:
Since response headers contain info about the page being sent to client,
RESPONSE headers should be sent **FIRST** before the page itself.
So when you echo or display something to the browser and then use the header() function,
<?php
echo "hi";
header("As you have already displayed "hi", this info will not be sent.);
?>
In the above code we have actually sent the page and then trying to send our header info,
so the headers will not be modified as the default headers were already sent and hence the error:
"Headers already sent".
Ans:
1) So, always include the header() function before displaying anything to the browser.
2)Another method to avoid the error is to use ob_start() function. This function just stores all the information that needs to be sent to the browser in a buffer memory, and it will output all at once.
Lets take a look at the code which will make more sense:
<?php
ob_start();
echo "hi";
echo "Hello"
header("This info will be sent");
ob_end_flush();
?>
In the above code, header info will be sent as both the echo statements will be stored in a buffer and will not be sent to the browser until the line ob_end_flush(); is executed. ob_end_flush() will just flush out the buffer memory sending all the info to the browser.
NOTE: But again make sure, you use the **ob_start()** function in the beginning.

jmeter help - test around polling /w meta refresh

I am new to jmeter and am working on putting together a test plan. The hurdle I've encountered is as follows:
First, a POST is made to processForm.aspx
Then, the user is redirected to pleaseWait.aspx
This page either redirects immediately to results.aspx OR loads, with a META REFRESH tag set to refresh in 5 seconds (and this step is repeated).
Now -- I can get this to execute by doing the following:
HTTP Sampler POST to processForm.aspx
Assert Response contains "<something on pleaseWait.aspx>"
While LAST
HTTP Sampler GET to pleaseWait.aspx
Assert Response contains "<something on results.aspx>"
However -- I don't care for this method, because it results in failed assertions (even though things are working as expected). I am sure there must be some other way to do this? Anyone more familiar with JMeter than I?
UPDATE:
Got it going by using Regular Expression Extractor instead of Assertions.
1) Add a User Defined Variables section at Test Plan Root
2) Add a variable to it "LoginWait" and "false"
HTTP Sampler POST to processForm.aspx
RegEx Extract Response Body contains "<something on pleaseWait.aspx>" into LoginWait
While ${LoginWait}
HTTP Sampler GET to pleaseWait.aspx
RegEx Extract Response Body contains "<something on pleaseWait.aspx>" into LoginWait
...
You could try using "follow redirects" on your HTTP Request. It would eliminate the logic you need, and still get you to the page you're going.

Change User Agent and Headers in pyWebkitGTK?

I've read the suggestions for making your own data handler, for example:
web_view.connect('resource-request-starting', resource_cb)
def resource_cb(view, frame, resource, request, response):
print request.get_uri()
#get data using urllib with different user-agent...
request.set_uri('data:....')
(from http://code.google.com/p/pywebkitgtk/wiki/HowDoI)
will let you download using custom header/useragent. However, sometimes it will complain if set_uri is given string with null-char, or it will give an error like "** Message: console message: (http://url) #linenumber: SECURITY_ERR: DOM Exception 18: An attempt was made to break through the security policy of the user agent."
Is there a better way to set a browser useragent for pygtk code? This says you can add/remove/replace headers using SoupMessage, however that documentation is missing...
This code sets a special user-agent:
http://nullege.com/codes/show/src%40p%40r%40PrisPy-HEAD%40PrisPy.py/33/webkit.WebView/python
webkit.WebSettings() allows user-agent switching, and a few other settings, but it seems it doesn't have the option to add other headers.