 Well, thank you all so much for coming when there's so many other good talks going on. My name's Rich Bowen. I've been working on the Apache web server project for a few years, about 15 years. And over that time, the web server has gone from being an exciting new thing to being just part of the plumbing. But there's some things that we've done in the latest version that I think are pretty cool. So we'll jump right in. The URL at the bottom of the screen there is where these slides live. If you want to grab a copy of them at some point, this URL will also be at the end. So 2.4 is new and improved, wash is brighter. A lot of the things that were done in 2.4 were done in order to make it more cloud-friendly. And so there's a lot of high availability kind of things. Proxying was a big deal in the 2.2 version and continues to be somewhere that we're doing a lot of improvements in 2.4 and 2.5. So I'm going to go ahead and jump right in with some of the low-level stuff. For those of you that have been around the Apache web server for a few years, you know that the multi-processing stuff in the web server has been very much the same since the very beginning. We've been using a pre-fork model, which is multiple processes, each one of which can handle connections. In the 2.0 days, we, it says 1997 or thereabout, we introduced threading, but it was never the default model. With 2.4, the event MPM becomes the default, it is a threaded MPM and MPM stands for multi-processing model or module, rather. And one of the hassles with the multi-processing stuff has always been that it was compiled statically into the core. And with 2.4, one of the major changes is that the MPMs are now runtime-loadable. And what this means is that it becomes much easier to experiment with different ones of the threading models to see if they work in your environment without having to reinstall the whole thing every time. So what you do is when you build this, you say I want to enable the MPMs shared. And then in your configuration file with a load module directive, you specify the MPM that you want to use. So we still have the old pre-fork model that's still available. And there are some situations in which you might want to use that. But the event MPM is now the default. So pre-fork is something that you might use in a situation where you're doing something that's not thread safe. So common wisdom is that if you're running a PHP application stack, you might want to stick with pre-fork, not because PHP itself is not thread safe, but because many of the libraries that live on top of PHP are not entirely thread safe. Unfortunately, there is not a definitive list of which those extensions are. So it's good to have a situation where you can swap out the MPM and test with it and then go back to a known good configuration if things don't work quite as well. The event MPM, the default MPM is determined based on the operating system capabilities. So if you're running a Linux, then the event will be the default MPM. All right. So moving up a little bit, one of the other great new features in 2.4 is the ability to configure your log level per directory or per module. Again if you've been around the web server for a while, you know that the log level is a server-wide configuration directive that says how loud your log files are going to be, how verbose they're going to be. The 2.4 version introduces a twist on this. So let's look at this first. This is the log level directive and in addition to setting the log level to a particular value and this is analogous to like syslog verbosity levels. So we set log level to info, but we want to get additional logging information from the SSL module and so we can now specify per module an additional verbosity there. And one of the things that this gives you in the past, if you wanted to get more verbose logging, error logging, you'd have to turn up log level across the board and certain modules are much noisier than others. So for example, if you're running modproxy and you turn log level up to debug, what you're actually looking for would be drowned in the noise from modproxy. So this is a way that you can now just say, I only care about SSL's debug information. Another thing that you can do now that you couldn't do before is log level per directory. So if I'm really only interested in debug information for a particular app that I'm running on my server, I can now specify that based on a directory or a URL location using the location directive. Yes? I'm sorry, but oh, I see. So the question is whether it will use the more verbose one or the more specific one if there's a conflict, it will use the more specific one. So if I say, if I add a proxy critical on there, then I will only see the modproxy messages if they're critical. It won't default to the more verbose one. So to me, this is the feature that says you should upgrade to 2.4 if you haven't already done so. This is something that people have been asking for literally since the day that I got involved in the web server project. And this is a more configurable configuration file, if you will, to be able to put conditionals in your configuration file. And these are request time evaluated configurations. So we have an if block and then also an else if and else. So they're going to look something like this. And of course, all of the things that I'm going to give examples of here were probably possible before using mod rewrite. And mod rewrite is the bane of every web server admin's existence. There is, you know, I should plug my book. I did write a book about mod rewrite and came out of the experience hating mod rewrite even more than before. But anyway, this syntax can do very much the same thing, but it's much more readable. You can kind of look at this and see what it says. So this example here takes a request for example.com and redirects it to www.example.com if you want a canonical host name. But it does it in a way that normal people can actually read without having to parse regular expressions. So I've actually got some other examples of this a little bit later in one of the other sections, but this is kind of the canonical example, if you will. Now another thing that comes with 2.4 that I'm really geeked about is mod macro. Mod macro has been around for 10 years, but it's always been a third party module. And it's been, it has lagged behind the main web server development. And so it's, it has tended to be a little bit difficult to get it to work sometimes. This was donated to the foundation to the web server project early this year or late last year and is now part of the 2.4 release. So mod macro lets you do cool stuff like this. You define a macro in your configuration file and then you invoke that macro several times. This allows you to create, so if you have a configuration that you're repeating a bunch of times, this allows you to simplify this. The most common scenario is the one that I've got here where you're defining 100 virtual hosts and your options for doing this in a dynamic fashion were kind of limited before. With mod macro, I create a macro and that macro takes in this, in this example. It takes two arguments, name and domain, which are then filled in throughout the macro. I invoke that macro several times and it creates those configuration blocks at server start-up time. And then evaluates the configuration as normal. That gets inserted right before the configuration evaluation phase. You can all, I've got the undef macro, you know, if you're doing macros multiple times, it's a good idea to clean up after yourself and that prevents variable space pollution. And you'll see in a moment why this becomes even more important in the 2.4 era. The if directive was introduced early in the 2.3 version for the 2.4 release and it became obvious that in order to have an if directive, we needed to have some sort of expression parser and so this was pulled out into a separate library and it gives a pretty much arbitrary expression parsing that you can stick in many different configuration directives if just is one of them. So any configuration directive where you might be doing some sort of comparison, you can do this, you can do it in a directory match block or a redirect or a rewrite or any one of these things. Once again, a lot of these things were possible before using convoluted mod rewrite things but this makes this a lot simpler. So here's the example that I showed you earlier, so nothing new there. We have an if directive but the thing in quotes in the if directive is passed off to the expression parser and returns true or false. So anything that you can put in there, any expression that you can think of to evaluate at request time, you can stick in there. Now in this case, I'm looking at a particular request header. You have access to of course all the request headers, all of the environment variables and perhaps cookies and other expressions that your PHP or your Tomcat container can generate you can evaluate those in these if blocks. So here's another example. I have a file that I want to serve as plain text and so I look in the query string for a particular value and based on that I set the mime type that this is returned as. Now yeah, you could do this with mod rewrite. It would have been painful and it would have been much less legible and to me that's the important thing here. This becomes very legible and your configuration file makes some sense, makes it more maintainable. Okay, apparently I didn't put the slide break in so I've got two slides here on one, two for the price of one here. This first example here is something cool that PHP programmers like. This is a feature in mod PHP that allows you to do source code pretty printing and here again I'm looking for a query string value. Suppose you put question mark source, it would then return the PHP source code syntax highlighted by using the PHP source handler. So that's kind of cool. But I can also in a require directive, so the require is the basic directive for access control and I can require a particular value in order to allow access to a resource and in this case I'm saying require that the time is between 9 a.m. and 5 p.m. otherwise we return a 402 unauthorized. Here's another favorite example that always comes up in the mod rewrite discussion. How do I prevent someone from loading my images on their website? And there are numerous recipes for this in the mod rewrite documentation. Here's a nice simple way to do it using the expression parser. So first of all I use a files match which allows me to check to see that an image is being requested. And then I use the if directive to say is the requesting host, and this example is wrong, that should say HTTP referrer. So what I should be checking here is that the referrer matches my host's host name, my virtual host's host name. And I'll correct that real soon. So the version that will be at the URL at the end will be correct. And then it just returns a require all denied. Now that syntax there require all denied may look a little bit odd if you have been using the Apache web server for some time and I'll come back to that in a moment. The syntax for that directive has changed in 2.4. Keep alive. So keep alive is a feature of the HTTP protocol that allows you to make multiple requests over the same socket. The way that HTTP works by default is that every resource is a separate TCP IP socket. So if you have a web page that has 50 images in it, that's 51 separate requests. Using keep alive you could stream those all over one connection or do them over several parallel connections. In the web server configuration there is a directive called keep alive time out. And that says, how long should I keep listening for the next request? One of the unfortunate side effects of this is that if there isn't a next request then I'm tying up that socket for no good reason. In the 1.3 days keep alive time out defaulted to I think it was 10 seconds and this made it really easy to do a denial of service attack on an Apache web server. You just open up 100 socket connections and then you just wait and the server would fall over. There was an automated version of this called slowloris a couple years ago. You may have heard of that. So we changed the keep alive time out down to one second which is still a long time when you're handling thousands of requests per second. Now you can set it to milliseconds. All of that to say, keep alive time out now accepts arguments in milliseconds rather than seconds giving you the ability to wait for say a quarter second rather than one or five seconds it just increases your responsiveness to the keep alive requests. Yes keep alive time out one still means one second. You can give it decimal values. So this change was really done for my personal benefit. I spend a lot of time on the IRC channel and the thing that people ask about the most is of course mod rewrite but closely following that is virtual host misconfiguration and virtual host configuration has always been very fragile. If you don't do it exactly right unexpected things happen and one of the things that people tend to get wrong is name based virtual hosting and it has to look like this. You have a name virtual host directive and then you have one or more virtual host blocks that exactly match that name virtual host directive. So if I say something like virtualhost www.example.com that doesn't work because it doesn't match the name virtual host directive. And so for years we would answer these questions on IRC and people would say why don't you just make the server smart enough to do the right thing. So we have finally done that. The name virtual host directive is deprecated. It will still work for now but you are encouraged to just remove the name virtual host directive and this will just do the right thing and if I put a server name in the virtual host line instead of the star.80 or star colon 80 it will do the right thing. It will just do what you mean now. It's about time. You know, several years ago I gave a conference presentation called Why I Hate the Apache Web Server. You may have seen this on Slashdot at the time. It was the only time I was ever slashed on it. And I'm proud to say that with this change everything that I complained about in that presentation has been resolved. So that's good. And you know, like I said, we were kind of sick of this in the support community because when people are consistently asking a question why isn't this easier then maybe the problem is with the code and not with the documentation or even with the end user. So that's just something that you should fix. This is a bellwether, you might say. Okay, here's another new configuration directive in 2.4 that's good for people who are doing service provider kind of hosting. If you have lots of people hosting sites on your servers this is a way to control them a little bit more tightly, a little bit more fine grained or perhaps relax restrictions. And this is around HT Access files. So HT Access files are a way for people to do per directory configuration by putting override directives in a local file that gets evaluated at request time. The way that this has been configured in the past is with the allow override directive and allow override takes an argument that specifies an entire group of directives. So you would say something like allow override auth config and that would allow them to use anything related to authentication or authorization but nothing else. Anything else would result in a server error. Sometimes that's not what you want. Sometimes you want to be able to give particular things that you want overridden. So I can say allow override none but allow these two configuration directives to be used. Or I can specify any one of the major categories but then also add to it say rewrite rule if I want people to be able to write rewrite rules in their HT Access files. I'm just trying to figure out how I'm doing on schedule. I think I'm right on track. Okay here's another really great feature in 2.4 that again people have been asking for forever and this is the ability to define variables in your configuration file and then use them later in the configuration file. Now I mentioned earlier mod macro and it uses variables. You have to be very careful to keep track of your namespaces and not overwrite existing variables because this is not a programming language it does not have good scope management so you need to keep track of that yourself, keep track of what variables you've used. But here's an example that is actually in the default configuration file that we ship with the source now. You have a define directive and then the variable that's defined in this case the document root is then used twice in the configuration file below it and this solves a common support problem where people will change the document root but will not change the directory block that configures access to that directory and so with this simple change we've solved a whole bunch of problems but also given you some power that you didn't have before so this is another one of my favorites. In addition to this there's always been the if define directive and the if define directive allows you to switch on or off blocks of configuration based on the existence of the value of variables and so you can use define with if define in order to say deploy one configuration file to all your servers but switch on and off different parts of it depending on what that particular server does. In addition to some of this new functionality that's in the core of the server there are a bunch of new modules that come with the 2.4 server and some of these, most of these were donated by companies that had developed them in house and now one of them to be part of the open source version. Hopefully I'm mentioning the most interesting ones, there are actually more than this. This one is worth mentioning if you're doing anything with say Python or PHP these are modules that allow you to deploy those apps as fast CGI apps so the documentation on these modules is not wonderful at the moment we're still working on that but there are lots of how to's online to get these things working. Here's another one of my favorites, this is mod proxy express. There's also the reason for the pony there is there's another module called mod pony and every time I see this module I think mod pony, kind of an inside joke in the support community. Anyway this module allows you to do, to quickly configure mass reverse proxies. So if you are in a, if you have a setup where you have one front end server and numerous back end servers that have basically identical configuration this allows you to do that in one configuration directive rather than having to configure each one individually. So here's what a proxy pass to a back end server looks like. We proxy pass everything to this back end server and then we also have to have a proxy pass reverse. The proxy pass reverse directive does fix up on HTTP headers. So imagine your back end server returns an HTTP header that says that it comes from that back end server. You don't want your end user to see that host name and so the proxy pass reverse fixes that up on the way through and you have to do that for every one of your back end proxies. With mod proxy express you create a text file mapping that shows a front end host name and the actual back end server that that maps to and then you generate a dbm file from that text file and then you feed that to mod proxy express and then mod proxy express takes that map file that we just generated and uses it to create these dynamic proxy blocks. Now suppose one of those back end servers goes offline, you update the file and the web server notices that the time stamp has changed and it reloads that. Now I've oversimplified just a little bit here because frequently you'll have more than one back end server for each one of these. So you just list them there. Base separated. Yes. It does not compare with varnish. So if you're using the Apache web servers or front end server chances are you can improve your performance by using varnish. There's another product called the Apache traffic server which compares very favorably to varnish and one of the advantages of the Apache traffic server is that they use the same configuration language but varnish is going to outperform this probably. Mod remote IP another thing that happens frequently when you are doing proxying is that your log files get screwed up and by that I mean that your back end log files show every request to be from the proxy server and there are ways to get around this and all of them are kind of klugey. Mod remote IP is a way to get around that well and it I mean the end result is that your back end servers see the original client IP address and so you can just run reports based on those log files rather than having to munch them. That's all that does. It's like one configuration directive. Here's a cool set of modules that were donated by Google and this is another set of modules that's for proxying environments. You run heartbeat on the back end server and you run heart monitor on the proxy end and they talk to one another so that when you when one of those back end servers goes down for some reason it gets quietly taken out of the rotation when it comes back up it gets put back in the rotation. Mod proxy balancer is a module that was added in 2.2 that does this load balancing stuff and so I'm not really mentioning it in this presentation but these two modules are components of Mod Proxy Balancer and Mod Proxy Balancer has a nice GUI front end, a web front end that allows you to add and remove back end servers from the proxy rotation and increase their priority or their load balancing methods. Load balancing methods are typically things like balance by traffic, make sure all the back end servers get the same number of requests or maybe balance by bytes, make sure that the back end servers serve comparable volumes of traffic. This is just a new balancing method and the heartbeat actually monitors the servers CPU usage, memory usage, you can configure it to balance based on anything having to do with the health of that back end server. Another proxy module is Mod Proxy HTML. This also was a third party module is developed by one developer, Nick Q and he donated this to the web server project about two years ago. So imagine a scenario where you're proxying a back end server that does things like perhaps that's cookies or perhaps has host names embedded in the HTML itself, perhaps it's a closed source product that you're proxying. Mod Proxy HTML allows you to rewrite all of that stuff as it's being served. It can rewrite links that are in the HTML, it can also rewrite host names in JavaScript and cookies so that what is actually served to the client doesn't break due to those embedded host names. Yes? Does it want now? So the question is I guess how much you can configure what this does. It's extremely configurable in, you know, if all you're interested in is rewriting the cookies, you can tell it to do that. Or you can tell it to just rewrite a portion of your content. So it's very configurable. It's exhaustively documented how all the different things that you can do with it. If you just set it up in its default configuration, it does in fact look through everything which can be very, very slow. So you want to be very careful how you configure this. Speaking of slow, here's another module that was donated by a third party and typically you would use this as a stop gap before you fix the actual problem. This is a way to do sed syntax filtering of content. So, you know, in my example here, I'm replacing days of the week with an abbreviation for the day of the week. Getting a sed command on everything that gets sent through the server is obviously going to be very slow. It's also potentially dangerous if you filter binary content by mistake. You can screw up image files pretty well, videos, whatever. But you know, like I say, it's a stop gap to solving the actual problem. Mod auth form and mod auth session are two modules that allow you to do form-based authentication within the web server. Everybody in the room, I'm sure, has written a login form of some kind. It's always the first thing you do on a project. This moves that code into the web server so that you don't have to do that. Unfortunately, this is not well documented at the moment. That's another thing that's on my list of things to do in the coming month. Mod session is a companion module that allows you to store that session information in cookies very similar to what PHP, for example, does with their sessions. It puts this into the web server. Any Lua programmers here? Okay, just one. Mod Lua is a lovely new module that allows you to embed Lua in the web server. Those of you that are familiar with Mod Pearl, somewhat older technology does the same thing with Pearl. It allows you to call any phase of the web server API from Lua. So it's a really great way, it's a very rapid way to develop applications in Lua on top of the Apache web server. Mod log debug is a great way to debug problems with your web server. It allows you to do, to inject log messages directly into the error log that have access to all of the various server variables. And then you can also do this based on the expression parser, so you can evaluate any expression. And you can do this based on particular hooks. So the hooks are the phases of the web server request. And there's about 30 different phases that this goes through that you can hook different modules to. The log message allows you to log at these various phases. So for example, if you have a variable that you're receiving in your script that is the wrong thing and you're not sure where it's getting screwed up, you could actually log it on hook equals all. And you'll see this big long line of log messages in your error log that follow the transition of this variable through all 30 some of those phases. And you can identify that moment that it makes the transition to the right or wrong value. That's a very powerful debugging technique. Mod rate limit is another very frequently requested feature. How do I make my web server run slower? But it's more than that, I'm hosting multiple clients and one of them has video downloads and they are completely consuming my pipe. So how do I limit just that portion of my web server? Here's how you do it now. You set a rate limit in kilobytes per second on a particular directory or location. There's actually another new module called mod modem. I'm not making this up. You can set the various modem standards. So you can say VBIS 9.2 and it'll configure it to be one of these old modem standards. So this is a lot friendlier. Sorry, what? It is location specific, yes. I mean, you could set it for an entire virtual host, but it is location or directory specific. I'm actually running a little bit low on time. This is one of the very important things in 2.4. This is a fairly significant syntax change. Now, the required directive is how you limit access control to various portions of your website. And it's very limited in 2.2 and earlier. You have allow from all and deny from all and you have to try to combine those in ways that make sense. And that's always been very difficult to get it as fine-grained as you really want it to be. So the required directive has numerous new syntaxes that allow you to do what you really mean. So first of all, we've got require all granted and require all denied. These are the blanket allow from all, deny from all. If you want to continue to use the old syntax, there is a module called mod off, mod off the compact. And that allows you to continue using the old syntax. So I expect that when people, when distribution starts shipping 2.4 as part of the default distribution, they will continue to use the old syntax with the compact module. That's my guess. I think that's what Fedora did when they first shipped 2.4. I have not yet seen the new Ubuntu configuration file. So I'm not sure what they're doing there. Then we have require various other things. So I can say require env and this allows me to specify a particular environment variable and you can set environment variables numerous different ways. So this gives you control of that from mod rewrite or from your application or from configuration directives. I can say require method and this allows me to restrict by HTTP method. So I can say require method get post and that will deny all other request methods. I can require by IP or host. And again, you could do this before but the syntax is now much more flexible. And it's got this great new thing require local. And that means any IP address of my local system, whether it's local host or the IPv6 local host address or just one of the IP addresses that happens to be on my system. And then I can do require by arbitrary expression. And this allows me to compare any request header or environment variable or variable that I have set within my configuration file. I can look in cookies. I can look all sorts of places for these variables that I can put in my expression. The next thing that I can do is combine several require directives in a require all or require any block. So these mean what they say. Require all means all of those have to have to evaluate to true or you can't get in. Similarly, this one says if any one of those evaluates to true, you can get in and then I can combine multiple ones of these by nesting them. And so it took me a few minutes to read this configuration block, but it's basically combining numerous LDAP configurations to say you can only get in here if you're an administrator and you're not a temporary employee and you're not in sales or wait, you might be in sales anyway. It combines several things here and it gives you a much more fine grain control that was simply not possible before. Require none means everything in here must evaluate to false. And if you use a require none in combination with something else, it does get a little bit confusing because all of these have to be, this one in particular says they can't be a temporary employee. All of these other things are invalid if they are in the, in the temp's group. And so it overrides everything else. You're of operations? No. Oh, so the question is whether there's an and or syntax. And I guess the and syntax is the require all and the or syntax. Is that for on the operator? There is not. In the in the in the expression evaluator. Yes, I'm sorry. I misunderstood. Yes, the expression evaluator does have an and an explicit and syntax. And so you could put in the expression several different statements and just put a literal and between them. Yes. So the question I believe is regarding mod rewrite backward compatibility. Mod rewrite syntax has not changed in this in this version. So everything that, that you know about mod rewrite already is, is still going to work. That's correct. The old, the old syntax will still continue to work. And I'm running both of the products that you mentioned on a 2.4 server, WordPress and Drupal and didn't have to change anything. But speaking of, of WordPress, here's a, an interesting change that, that this is what I use on my WordPress server. This is a directive that was actually introduced in 2.2. Actually, it was introduced in 2.4 and back ported to 2.2. But this is, this thing down here at the bottom, the second black example there is the WordPress HD access file. And it says, anytime somebody requests a URL that doesn't really map to anything, serve index.php instead. This is called the front controller model. Basically all your requests go through the index.php. This gets a little bit complicated if you have content on your server that is not that controller. So perhaps you have a, an alias and you have to explicitly mention that alias in here, otherwise it gets mapped to the WordPress handler in this case. The fallback resource directive takes that entire block and condenses it to one line. It's essentially works as a 404 handler. Anytime something that is requested does not exist as a, as a resource. Whether that's an on file resource or an alias or a redirect, it will fall back to this other resource. And so you can replace your WordPress HD access file with this one directive. And I typically do, so that's, that's a really cool time saver. And I have about five minutes left for questions. There are other new features that I have not mentioned. But I think that I've just left out the boring stuff. Of course, you may have a different definition of boring than I do, I hope. So I hope I wasn't terribly boring. But has anybody got any questions? Yes. Can I elaborate authentication? I'm trying to remember what I said that, oh, mod auth form. So mod auth form is a module that allows you to implement form based authentication and so you embed a form in your HTML and it gets passed to mod auth form and it can validate that authentication against a variety of back end things including a SQL type server or text file. What is not ready with that is the documentation. The documentation basically says what I just said. And it needs to be more explicit than that. It needs to have examples. It needs to have an actual functional example in there before it's particularly useful. So that's my biggest complaint with the module right now. Yes, yeah, that's gonna be pretty cool. Speaking of databases, another feature that I neglected to mention is that mod rewrite has a directive called rewrite map that allows you to pass a rewrite directive to some back end thingy, whether that's a text file or a script. It's now, you can actually put an SQL query directly in your rewrite map directive. And so it will query your database and use that as the results for rewrite map. That's a new feature in 2.4. Yes. Yes. The complexity will just remain there, but why are they recommended and require any, if else, statements? Yeah, that's a legitimate observation. You're translating, if you rewrite your rewrite rules into some other syntax, you're moving your complexity elsewhere. I find the syntax to be significantly easier to read. But yeah, you're right. You do typically end up with a similar number of actual configuration lines. But typically when I've given a talk where I show the mod rewrite example and the new syntax example, people tend to agree that the new one's easier to read, easier to maintain. So I don't know. I guess it depends on your preference. I've been doing mod rewrite for so long that it's hard for me to be objective in comparing them. So I don't know. Yes, sir. So the question is whether upgrading to 2.4 will break an existing configuration. The main things that are likely to break are the require syntax. And you can get around that by loading mod auth compact. And that'll use the old syntax. The other thing is that if you're doing virtual hosting, you'll get a warning about the name virtual host directive. It'll just be a warning on startup. It won't fail to start. And you can remove that line to remove the warning. Other than that, all of the various configurations should be completely backward compatible. So there shouldn't be any difficulty. Yes. I'm afraid I'm not able to answer that question directly. The person who can is here at the conference. It's Jim Jogilski. But in a general answer to your question, yes, those expressions are compiled at server startup time so that they can be executed on each request. But they do have an impact on performance, but I have not noticed it to be significant. And I guess it depends what you're comparing it to as well. Because it performs almost the same as doing the things in mod rewrite. It tends to be faster than mod rewrite in most situations. But the caveat there is because you can write pretty much any expression, you can make that as complicated as you want. You can impact your performance by making things overly complicated. But so far as the exact implementation, you might want to corner Jim Jogilski if you see him look for his picture on Wikipedia. OK, well, I am completely out of time. Thank you all so much for coming. Was there another question? Yeah, I just want to know. Yes. So a lot of the effort in 2.4 was actually on cleaning up code and reducing memory consumption. And so switching from 2.2 to 2.4 using exactly the same feature set, you will reduce memory consumption significantly. I don't have actual numbers on that. But again, Jim Jogilski has done a lot of testing on that. And he's written a number of articles in which he has said that performance, that the common wisdom that Nginx is so much faster is no longer true with 2.4. Now, of course, any time you compare two web servers, it depends what you're doing. It depends how well you know how to configure them. But his assertion is that we've caught up so far as speed goes with Nginx. And of course, they just had a new release a couple weeks ago, so maybe they're ahead again, we'll see. But it is very much an even race between those two. And memory consumption is way down from 2.2. Thank you.