Http content negotiation issues

Hello all,
I was experimenting with http content negotiation and I was having some issues.
When I run an if-statement that prints if it supports it or not (I am checking for svg support)
Here is the code:

<!Doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<title>Content Negotiation</title>
	</head>
	<body>
		<?php
			if (stristr($_SERVER["HTTP_ACCEPT"], "image/xml+svg")) {
				echo "I support SVG as a css background-image!";
			}
			else{
				echo "I don't support SVG as a css background-image!";
			}
		?>
	</body>
</html>

But, here is my problem: browsers that do support svg images/documents as a background image via css, are saying that they do not accept this header :confused::mad::frowning:

And I doubled check this by explicitly defining an svg image/document as a background-image of the body and they accepted the image, but not the header…?
For example, in chrome, it supports the explicit definition, but not the above code. :confused:

Here is a live example

Am I looking for the support of the wrong mime type? That might be why its not accepting the header because the header I am checking for isn’t the right one (for support for svg images as a background-image)?

Does anyone have any ideas on why this isn’t working. Am I writing the condition in the if-statement right or is it something else?

I hope to hear from you soon and Please let me know if you have any Questions, Comments, Concerns, or Solutions please let me know :slight_smile:

Thanks in Advance & Best Regards,
Team 1504

You should review the HTTP headers the browser is sending when requesting your page. Firefox for example, its content Accept header is context sensitive. When requesting and HTML page it sends: “text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8” while requesting an image: “image/png,image/;q=0.8,/*;q=0.5” This is on Firefox 7, Windows 7, default settings.

wait, how do I figure that out ?

And wouldn’t the syntax be browser-specific then? MeaningI would have to do an if statement for each browser based on what it, specifically sends?

And then if so, would firefox 7’s syntax be this:

<?php
if (stristr($_SERVER[“HTTP_ACCEPT”], “image/png,image/;q=0.8,/*;q=0.5”)) {
echo “I support png”;
}
else{
echo “I don’t support png”;
}
?>

You might have to do SVG detection via javascript, rather than PHP.

Example: http://stackoverflow.com/questions/654112/how-do-you-detect-support-for-vml-or-svg-in-a-browser

I would seriously prefer to not do it in js, because then there is the possibility of js being turned off.

Especially if there is a way to do it in a language that can not be disabled.

And especially, if the code in the PHP makes sense and should work…

Apologies if I am being stubborn, but I will resort to that if necessary. But for now, at least, I want to learn why the php code is not working.

Its not working because Chrome is not sending “image/xml+svg” in the Accept header. Nothing in PHP can change that.

Furthermore, my previous reply I was telling you to use the whole string. The Accept header has a special format which can be reviewed here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

Okay, now I am leaning towards the js path as much as I dont want to…
But I still have some questions :
Apologies for being a noob, but now I am wondering why the hell doesn’t chrome accept or send that header?
Isn’t image/svg+xml the official header?

Does anyone know if any browsers accept / send for this header?

Since we already know chrome doesn’t accept /send for this header, what header does chrome accept /send send for SVG?
So that I can check for SVG support in chrome, right?

And lastly, how do I found out what header a/any browser accepts or sends for in terms of SVG

Thank you all again! :slight_smile:

Hmm I thought of an idea and before I try it, I want to run it by you guys.
Please let me know if you have any comments or suggestions on it

What if I changed the header for .svg files in the .htacess file in the root of my server. Would that allow and tell chrome, and other browsers to send for and accept said header when looking for .svg files?

Meaning in apache, I don’t have the syntax on me, but if I set the header to image/svg+xml for .svg files, then wouldn’t that make the browser look for / send / accept that explicitly mentioned header?

I tried adding the following to my .htacess file hoping that it would allow the browsers to know what MIME type = svg


AddType     image/svg+xml      svg svgz 
AddEncoding gzip                    svgz

so that when I ask if they accept the header with that MIME-type, they say so if they accept it and no if they do not.

But it still yielded the same results: echoing that they do not support svg, even though I have manually tested and confirmed that certain browsers do
:(:(:(:(:(:(:(:(:confused::confused::confused::confused::confused:

I also just found out that it is possible to do content negotiation. As Wikipedia does it to serve svg if supported.

Actually, your code isn’t testing for support, but for HTTP_ACCEPT headers, hence the difference between your echo message and the actual results.

AFAIK, there is no way to “force” any browser to send any HTTP headers let alone specific ones. Either they do or they don’t.

But, there’s a good possibilty you can work something out.

I guess the first thing to do is to find out what they are sending. The first and easiest step would be a simple PHP page with something like


if ( isset($_SERVER["HTTP_ACCEPT"]) )
{
echo $_SERVER["HTTP_ACCEPT"];
}else{
echo 'no HTTP ACCEPT header';
}

Then it becomes more work.

To test if they send the headers with the request for the CSS file, you could add a line to your htaccess file redirecting requests for “headertest.css” to “headertest.php” - if - the headers don’t get lost during the redirect, you could then have the value emailed to you or logged to a database.

Then try the same technique with “headertest.svg”.

Th

AFAIK, there is no way to “force” any browser to send any HTTP headers let alone specific ones. Either they do or they don’t.

Yeah, I found that out after trying it. I was skeptical, but quite hopeful that it would somehow end my quest. But, it didn’t.

Actually, your code isn’t testing for support, but for HTTP_ACCEPT headers, hence the difference between your echo message and the actual results.

Oh okay. I thought that by testing for HTTP_ACCEPT headers, it was implying / indirectly testing for support.
So the difference between the echo message and the actual results in browsers that support svg was due to the fact that there were no HTTP_ACCEPT headers to test. Thats why it resorted to the else. Is that right, or did I mess it up ? :blush:

Then it becomes more work.

Because after checking what support they have, one / we would have to interpret the results.

But then, here is where it gets really confusing for me:

To test if they send the headers with the request for the CSS file, you could add a line to your htaccess file redirecting requests for “headertest.css” to “headertest.php” - if - the headers don’t get lost during the redirect, you could then have the value emailed to you or logged to a database.

I do not know if you would be willing to explain it differently because I am confused. But first can I give my understanding or what I thought you were saying and then you can see if I understood it correctly?

I understood it as…
1.) It becomes more work to interpret the results and check what HTTP_ACCEPT headers they are sending. And then react accordingly.
2) So first: If we see if the browser is correctly interpreting the link to a stylesheet** by sending an HTTP_ACCEPT request for it.
3.) Then, If it is sending for it, then use some syntax in the .htaccess file to redirect that request to a php file
4.) A PHP file that has code like what I posted in my first post. Which, checks if supports svg and if so provides styling with an svg image. Or if not, then styling with another format of widely-supported image (PNG, JPG, GIF)

*Having any lost requests emailed to be or logged in a db is just error checking. Which may happen due to all the detours and redirects, right?

**A stylesheet that just has styling to place the svg image / png image. Because it was all of the page’s styling, once t figure out what type of image it should return, it would echo styling just for that image and not that whole original stylesheet
What do you think? Did I get it? :lol:

Again, Thank you ever so kindly— seriously. :slight_smile:

With all Regards, Gratitude, and Respect,
Team 1504

Javascript:

function supportsSvg() {

    return document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")
}

Then go about replacing bitmap images with SVG images if thats what you need. Or have Javascript save it to a cookie then access it with PHP on new page loads.

thank you. im going to play around with it.
like before Mittineague’s post, I was experimenting with Force Flow’s technique.

But since wikipedia does it with php, it must then be possible with php.

Apologies for my reluctancy in regards to using JS, but i prefer to use it as little as possible. And when there are no other options. I don’t mean to be rude at all, I am quite grateful for the solutions, but there is a reason why I posted this in the PHP forum.

Now, since I have been looking and asking around, and not much is turning up in terms of a PHP solution, I have started working the js solutions.
But, at the last moment, I read that wikipedia does it in PHP successfully.

It is as if PHP HTTP Content Negotiation is taunting me!:lol: :frowning:

EDIT: I am sincerley sorry if I sounded rude in this post. I really can’t express how thankful I am for all of yours help. :slight_smile:

What Wikipedia does it probably by sniffing the User Agent string which is bad.

im a noob at this stuff, if you haven’t already figured out already, what is sniffing the User Agent string / what does it do?
And how is it / how can it be bad? Is it unreliable?

Honestly, not only do I want to solve this problem, but I also wan to learn a lot from it :slight_smile:

I found another thread with the similar issue at codingforums.com, here

It seems like they encountered the same problem. That browsers that should or do support svg say they do not. And that is because the svg mime-type does not show or is a part of the HTTP_ACCEPT header.

The OP there seemed to accept that it was not possible that way,so he/she alluded to resorting to something else. But, that was about 5 years ago.

And it seems like there should be a solution by now.

I will attempt to contact him / her, but in the meantime, can anyone answer my questions regarding user agent string sniffing and why it is bad?

It is what was used in the old days, akin to the wild west to determine if a user was on IE or Netscape and deliver specific content to one or the other.

Yes, I’d try to avoid using USER AGENT. Kind of like saying “if the browser says who it is I can assume they have certain capabilities”. Much better to directly test if they have the needed capability rather than assume. i.e. the javascript logic_earth posted.

I guess you kind of understood, but the email/db is not for error checking. It’s only so you can find out what headers are sent with what HTTP request.

Every file is called via an HTTP request, so as nice as it would be for a browser to send everything with the page request, I imagine they might send different for the page, the CSS file, and the SVG image. And most likely every browser does things their own way. Doesn’t make things easy, but it doesn’t mean it’s impossible.

If you try adding

RewriteRule /?svgtest.svg$ /svgtest.php [L]

to your htaccess file and have svgtest.php something like

$ubject = 'SVG Header test';
$message = 'Accept Header: ' . $_SERVER["HTTP_ACCEPT"];
$to = '[your email address here]';
$headers  = "MIME-Version: 1.0 \\r\
" ;
$headers .= "Content-Type: text/plain \\r\
";
$headers .= "From: <[yourname@yoursite.com here]> \\r\
\\r\
";
mail($to, $subject, $message, $headers);

Don’t try this in a page that’s already up or you might get a flood of emails, put it in a page only you know about.

Hmm okay, makes sense. Instead of looking for browsers that are supposed to support something, looking for that support.

So now I added the server config to my .htacess file. The only other thing there are mime-types.

Here is my entire .htacess file:
RewriteRule /?svgtest.svg$ /svgTest.php [L]

# ----------------------------------------------------------------------
# Proper MIME type for all files
# ----------------------------------------------------------------------

AddType application/javascript               js

# Audio
AddType audio/ogg                              oga ogg
AddType audio/mp4                             m4a

# Video
AddType video/ogg                              ogv
AddType video/mp4                              mp4 m4v
AddType video/webm                            webm

# SVG.
AddType     image/svg+xml                   svg svgz 
AddEncoding gzip                                 svgz
                                       
# Webfonts                             
AddType application/vnd.ms-fontobject    eot
AddType application/x-font-ttf                ttf ttc
AddType font/opentype                         otf
AddType application/x-font-woff             woff

# Assorted types                                      
AddType image/x-icon                          ico
AddType image/webp                           webp
AddType text/cache-manifest                appcache manifest
AddType text/x-component                   htc
AddType application/x-chrome-extension crx
AddType application/x-xpinstall              xpi
AddType application/octet-stream          safariextz
AddType text/x-vcard                          vcf

And then I created the file svgTest.php and it contains only the following:

$subject = 'SVG Header test';
$message = 'Accept Header: ' . $_SERVER["HTTP_ACCEPT"];
$to = '[****@gmail.com]';
$headers  = "MIME-Version: 1.0 \\r\
" ;
$headers .= "Content-Type: text/plain \\r\
";
$headers .= "From: <[****@gmail.com]> \\r\
\\r\
";
mail($to, $subject, $message, $headers);

#Note, the to email is that same as the from-header email. Was I supposed to do this? I assumed explicitylt assigning it to my email because there is no form to give it the actual sender's email.

Now, If I know my apache / .htaccess well enough, the code you told me to put in the .htacess sends the user to svgTest.php when they visit svgtest.svg, right?

But my question is why do that? The user is never going to visit the svg, it will be loaded as a svg css background-image. Also why redirect the user to a file that emails me especially if that original file will never be visited?
I don’t understand / what is the point of sending me the email?

After reading your, Mittineague 's, post again, I see the point of the email is to learn what headers are sent.

But from then on, what do I do? Or in better context, am I supposed to compare the HTTP_ACCEPT header for svg to the data the e-mail set e. Thus, seeing if it is one of the headers a browser accepts and if so, then serve an svg image?

Regards,
Team 1504

P.S. Here is a link to the svgtest.