symfony posts page 2

Struggling to figure out why every response from my Symfony application is showing up in the log files as a ‘200’ status. I thought it was related to this and this, since I’m running under FastCGI on Dreamhost, but attempting to set a Status header didn’t help. Setting a regular response header in a plain PHP file does work, in fact. If I use ‘mod_rewrite’ to write another URL to load that same plain file, however, the status shows as ‘200’, so it must have something to do with ‘mod_rewrite’. Must get to bed though, so I will have to try another day.


Security HTTP Headers

I’ve been working on the HTTP headers my site sends recently. I had been working on performance / cache related headers, but after seeing mention of a security header scanner built by Scott Helme, I decided to spend a little time implementing security related headers on my site. I don’t really know these headers that well, so I added the headers it suggested and mostly went with the recommended values. I did read up a bit on what they mean though and modified the Content-Security-Policy as I saw fit.

I added most of the headers using a Symfony reponse event listener. This handles all of my HTML responses without sending the headers for other responses, where they aren’t necessary. The exception is the X-Content-Type-Options, which should be set for all responses. I set that in Apache configuration.

Continue reading post "Security HTTP Headers"

Symfony AppCache and ‘X-Reverse-Proxy-TTL’, a hack

Symfony’s HttpCache reverse proxy is a simple way to get caching of pages with Symfony. It is simple to set up, easy to work with, and easy to clear. I started using it recently on my own site.

A simple app/console cache:clear will clear the entire cache. Otherwise, following the HTTP-oriented spirit of the framework, invalidation is based entirely on HTTP headers. In this way, it works the same as proxy / gateway caches. It only caches responses with public Cache-Control headers. It is age based, using the Cache-Control s-maxage or maxage values or Expires headers (following that order of precedence). It then considers the cached items fresh until they are stored for longer than those headers specify they can be stored. The cached version is served, bypassing the router / controller, as long as the cache is fresh.

This is all nice, but using long max-ages for those headers means that caches outside of my control can cache pages for long periods of time. cache:clear won’t help when a page changes. One possible option would be to have shorter and safer max-ages as Cache-Control headers and use something else for HTTPCache.

Continue reading post "Symfony AppCache and ‘X-Reverse-Proxy-TTL’, a hack"

404 with autofilling form

Inspired by a tweet by @simevidas about a 404 page search form, I decided to finally replace Symfony’s default 404 page on my site. The tweet was about an example site’s 404 pages that take pieces from the URL path to populate a search field. Upon seeing it, I immediately thought how easy it would be to implement a simple version of that.

I had been thinking of customizing my 404 for a while, but stopped trying because Twig doesn’t seem to know about bundle paths in the error pages, preventing me from extending the “base” template in my bundle. I still didn’t find a solution for this, so the 404 page has an unstyled look, but I wanted to capture the search form idea while it was on my mind.

Looking into 404 best practices, I found three things that I wanted on mine: branding, guidance / next steps for the user, and small size / low power.

Continue reading post "404 with autofilling form"

Symfony AppCache: built in reverse HTTP proxy

I finally set up my site to work with Symfony’s built in HTTP reverse proxy. Took a little bit of time since I had to fix a couple minor bugs in how things are set up with my symfony-initial and Symfony Standard Edition Bundle and then made a mistake in testing whether or not it was working that made me think it wasn’t when it was.

One useful way to test if it’s working is to set the ‘debug’ option of AppCache to true (turn this back off for production). This will set an X-Symfony-Cache header that will provide info on the cache behaviour. You can see these headers on the shell by running curl -I your.url. If it says ‘fresh’ as part of the header value, that means it was served from the cache. If it shows the header at all, that means AppCache is being used.

For the cache to work, the response must be public and have something set to control how the cache becomes stale. See Symfony’s docs on caching for more details. Since my content rarely changes at the moment, I went with the Cache-Control header with max-age. A cool thing about using Symfony’s reverse proxy is that the entire cache will be cleared when clearing Symfony’s cache like normal. This means that if you make a mistake and must remove it from the cache, there is a quick and easy way.


Load Balancers and HTTPS

Until recently, I had no experience working with sites behind load balancers. Cogneato has been moving its sites to Rackspace virtual servers for flexibility, among other things. One of their recommendations that we took was to put our web server behind a load balancer. Even though we haven’t needed multiple nodes behind it yet, it makes it easier to upgrade the server behind it without needing to change IPs in DNS and will allow us to easily pop up another node when it is needed.

This arrangement has gone relatively smoothly except a few issues. The biggest ones have had to do with our HTTPS sites. We run both HTTP and HTTPS sites on the same server. We put the certificates on the load balancer, so traffic goes from the load balancer to the web server over HTTP. Both Apache and code see the request as HTTP as standard methods are concerned. I will discuss some of the problems we had and solutions I found.

Continue reading post "Load Balancers and HTTPS"

Additive overwriting of Symfony security configuration

Symfony provides a security component and bundle for managing authentication and authorization in an application. It is versatile and powerful, if not a bit complicated. You can toss as many mixes of authentication and authorization configuration as you want. The important parts of the configuration cannot be overridden or added to by multiple config files, though. This makes sense for one-off applications, where you can be sure that no bundles are messing with your security configuration. However, if you’re building something like a CMS that will be used for multiple sites, where you want the CMS’s bundle to manage security, setting the configuration within the bundle will block the application itself from adding its own configuration.

One way I’ve found to work around this is to have the security configuration set on your bundles configuration extension instead of the ‘security’ extension directly, and have your bundle merge all such configurations and set them on the ‘security’ extension in PHP. If you allow this configuration node to be overridden, any number of bundles can add to it and avoid the “cannot be overwritten” error.

Continue reading post "Additive overwriting of Symfony security configuration"