{"id":945,"date":"2016-10-11T09:20:09","date_gmt":"2016-10-11T07:20:09","guid":{"rendered":"http:\/\/www.netnea.com\/cms\/?page_id=945"},"modified":"2025-11-07T10:41:11","modified_gmt":"2025-11-07T09:41:11","slug":"apache-tutorial-2_minimal-apache-configuration","status":"publish","type":"page","link":"https:\/\/www.netnea.com\/cms\/apache-tutorial-2_minimal-apache-configuration\/","title":{"rendered":"Configuring a Minimal Apache Web Server"},"content":{"rendered":"\n<h2 id=\"configuring-a-minimal-apache-server\">Configuring a minimal Apache server<\/h2>\n<h3 id=\"what-are-we-doing\">What are we doing?<\/h3>\n<p>We are configuring a minimal Apache web server and will occasionally be talking to it with curl, the TRACE method and ab.<\/p>\n<h3 id=\"why-are-we-doing-this\">Why are we doing this?<\/h3>\n<p>A secure server is one that permits only as much as what is really needed. Ideally, you would build a server based on a minimal system by enabling additional features individually. This is also preferable in terms of understanding what\u2019s going on, because this is the only way of knowing what is really configured. Starting with a minimal system is also helpful in debugging. If the error is not present in the minimal system, features are added individually and the search for the error goes on. When the error occurs, it is identified to be related to the last configuration directive added.<\/p>\n<h3 id=\"requirements\">Requirements<\/h3>\n<ul>\n<li>An Apache web server, ideally one created using the file structure shown in <a href=\"https:\/\/www.netnea.com\/cms\/apache-tutorial-1_compiling-apache\">Tutorial 1 (Compiling an Apache web server)<\/a>.<\/li>\n<\/ul>\n<h3 id=\"step-1-creating-a-minimal-configuration\">Step 1: Creating a minimal configuration<\/h3>\n<p>Our web server is stored in <code>\/apache<\/code> on the file system. Its default configuration is located in <code>\/apache\/conf\/httpd.conf<\/code>. It is very extensive and contains many comments and commented out configuration lines. This makes it rather difficult to understand but at least everything is still in a single file. For packaged versions of Apache, on many Linux distributions, the default configuration is not only very complicated, it is also fragmented into a handful of separate files that are spread across multiple directories. This can make it hard to get a good overview of what is actually going on. To simplify things, we will be replacing this extensive configuration file with the following, greatly simplified configuration.<\/p>\n<div class=\"sourceCode\" id=\"cb1\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb1-1\"><a href=\"#cb1-1\" aria-hidden=\"true\"><\/a><span class=\"ex\">ServerName<\/span>              localhost<\/span>\n<span id=\"cb1-2\"><a href=\"#cb1-2\" aria-hidden=\"true\"><\/a><span class=\"ex\">ServerAdmin<\/span>             root@localhost<\/span>\n<span id=\"cb1-3\"><a href=\"#cb1-3\" aria-hidden=\"true\"><\/a><span class=\"ex\">ServerRoot<\/span>              \/apache<\/span>\n<span id=\"cb1-4\"><a href=\"#cb1-4\" aria-hidden=\"true\"><\/a><span class=\"ex\">User<\/span>                    www-data<\/span>\n<span id=\"cb1-5\"><a href=\"#cb1-5\" aria-hidden=\"true\"><\/a><span class=\"ex\">Group<\/span>                   www-data<\/span>\n<span id=\"cb1-6\"><a href=\"#cb1-6\" aria-hidden=\"true\"><\/a><span class=\"ex\">PidFile<\/span>                 logs\/httpd.pid<\/span>\n<span id=\"cb1-7\"><a href=\"#cb1-7\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-8\"><a href=\"#cb1-8\" aria-hidden=\"true\"><\/a><span class=\"ex\">ServerTokens<\/span>            Prod<\/span>\n<span id=\"cb1-9\"><a href=\"#cb1-9\" aria-hidden=\"true\"><\/a><span class=\"ex\">UseCanonicalName<\/span>        On<\/span>\n<span id=\"cb1-10\"><a href=\"#cb1-10\" aria-hidden=\"true\"><\/a><span class=\"ex\">TraceEnable<\/span>             Off<\/span>\n<span id=\"cb1-11\"><a href=\"#cb1-11\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-12\"><a href=\"#cb1-12\" aria-hidden=\"true\"><\/a><span class=\"ex\">Timeout<\/span>                 10<\/span>\n<span id=\"cb1-13\"><a href=\"#cb1-13\" aria-hidden=\"true\"><\/a><span class=\"ex\">MaxRequestWorkers<\/span>       100<\/span>\n<span id=\"cb1-14\"><a href=\"#cb1-14\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-15\"><a href=\"#cb1-15\" aria-hidden=\"true\"><\/a><span class=\"ex\">Listen<\/span>                  127.0.0.1:80<\/span>\n<span id=\"cb1-16\"><a href=\"#cb1-16\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-17\"><a href=\"#cb1-17\" aria-hidden=\"true\"><\/a><span class=\"ex\">LoadModule<\/span>              mpm_event_module        modules\/mod_mpm_event.so<\/span>\n<span id=\"cb1-18\"><a href=\"#cb1-18\" aria-hidden=\"true\"><\/a><span class=\"ex\">LoadModule<\/span>              unixd_module            modules\/mod_unixd.so<\/span>\n<span id=\"cb1-19\"><a href=\"#cb1-19\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-20\"><a href=\"#cb1-20\" aria-hidden=\"true\"><\/a><span class=\"ex\">LoadModule<\/span>              log_config_module       modules\/mod_log_config.so<\/span>\n<span id=\"cb1-21\"><a href=\"#cb1-21\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-22\"><a href=\"#cb1-22\" aria-hidden=\"true\"><\/a><span class=\"ex\">LoadModule<\/span>              authn_core_module       modules\/mod_authn_core.so<\/span>\n<span id=\"cb1-23\"><a href=\"#cb1-23\" aria-hidden=\"true\"><\/a><span class=\"ex\">LoadModule<\/span>              authz_core_module       modules\/mod_authz_core.so<\/span>\n<span id=\"cb1-24\"><a href=\"#cb1-24\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-25\"><a href=\"#cb1-25\" aria-hidden=\"true\"><\/a><span class=\"ex\">ErrorLogFormat<\/span>          <span class=\"st\">&quot;[%{cu}t] [%-m:%-l] %-a %-L %M&quot;<\/span><\/span>\n<span id=\"cb1-26\"><a href=\"#cb1-26\" aria-hidden=\"true\"><\/a><span class=\"ex\">LogFormat<\/span>               <span class=\"st\">&quot;%h %l %u [%{%Y-%m-%d %H:%M:%S}t.%{usec_frac}t] <\/span><span class=\"dt\">\\&quot;<\/span><span class=\"st\">%r<\/span><span class=\"dt\">\\&quot;<\/span><span class=\"st\"> %&gt;s %b \\<\/span><\/span>\n<span id=\"cb1-27\"><a href=\"#cb1-27\" aria-hidden=\"true\"><\/a><span class=\"dt\">\\&quot;<\/span><span class=\"st\">%{Referer}i<\/span><span class=\"dt\">\\&quot;<\/span><span class=\"st\"> <\/span><span class=\"dt\">\\&quot;<\/span><span class=\"st\">%{User-Agent}i<\/span><span class=\"dt\">\\&quot;<\/span><span class=\"st\">&quot;<\/span> combined<\/span>\n<span id=\"cb1-28\"><a href=\"#cb1-28\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-29\"><a href=\"#cb1-29\" aria-hidden=\"true\"><\/a><span class=\"ex\">LogLevel<\/span>                debug<\/span>\n<span id=\"cb1-30\"><a href=\"#cb1-30\" aria-hidden=\"true\"><\/a><span class=\"ex\">ErrorLog<\/span>                logs\/error.log<\/span>\n<span id=\"cb1-31\"><a href=\"#cb1-31\" aria-hidden=\"true\"><\/a><span class=\"ex\">CustomLog<\/span>               logs\/access.log combined<\/span>\n<span id=\"cb1-32\"><a href=\"#cb1-32\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-33\"><a href=\"#cb1-33\" aria-hidden=\"true\"><\/a><span class=\"ex\">DocumentRoot<\/span>            \/apache\/htdocs<\/span>\n<span id=\"cb1-34\"><a href=\"#cb1-34\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-35\"><a href=\"#cb1-35\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span><span class=\"ex\">Directory<\/span> \/<span class=\"op\">&gt;<\/span><\/span>\n<span id=\"cb1-36\"><a href=\"#cb1-36\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-37\"><a href=\"#cb1-37\" aria-hidden=\"true\"><\/a>    <span class=\"ex\">Require<\/span> all denied<\/span>\n<span id=\"cb1-38\"><a href=\"#cb1-38\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-39\"><a href=\"#cb1-39\" aria-hidden=\"true\"><\/a>    <span class=\"ex\">Options<\/span> SymLinksIfOwnerMatch<\/span>\n<span id=\"cb1-40\"><a href=\"#cb1-40\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-41\"><a href=\"#cb1-41\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>\/<span class=\"ex\">Directory<\/span><span class=\"op\">&gt;<\/span><\/span>\n<span id=\"cb1-42\"><a href=\"#cb1-42\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-43\"><a href=\"#cb1-43\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span><span class=\"ex\">VirtualHost<\/span> 127.0.0.1:<span class=\"op\">80&gt;<\/span><\/span>\n<span id=\"cb1-44\"><a href=\"#cb1-44\" aria-hidden=\"true\"><\/a>      <\/span>\n<span id=\"cb1-45\"><a href=\"#cb1-45\" aria-hidden=\"true\"><\/a>      <span class=\"op\">&lt;<\/span><span class=\"ex\">Directory<\/span> \/apache\/htdocs<span class=\"op\">&gt;<\/span><\/span>\n<span id=\"cb1-46\"><a href=\"#cb1-46\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-47\"><a href=\"#cb1-47\" aria-hidden=\"true\"><\/a>        <span class=\"ex\">Require<\/span> all granted<\/span>\n<span id=\"cb1-48\"><a href=\"#cb1-48\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-49\"><a href=\"#cb1-49\" aria-hidden=\"true\"><\/a>        <span class=\"ex\">Options<\/span> None<\/span>\n<span id=\"cb1-50\"><a href=\"#cb1-50\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-51\"><a href=\"#cb1-51\" aria-hidden=\"true\"><\/a>      <span class=\"op\">&lt;<\/span>\/<span class=\"ex\">Directory<\/span><span class=\"op\">&gt;<\/span><\/span>\n<span id=\"cb1-52\"><a href=\"#cb1-52\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb1-53\"><a href=\"#cb1-53\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>\/<span class=\"ex\">VirtualHost<\/span><span class=\"op\">&gt;<\/span><\/span><\/code><\/pre><\/div>\n<h3 id=\"step-2-understanding-the-configuration\">Step 2: Understanding the configuration<\/h3>\n<p>Let\u2019s go through this configuration step-by-step.<\/p>\n<p>We are defining <em>ServerName<\/em> as <em>localhost<\/em>, because we are still working in a lab-like setup. In production the fully qualified host name of the service has to be entered here.<\/p>\n<p>The server requires an administrator e-mail address, primarily for display on error pages. This is defined in <em>ServerAdmin<\/em>.<\/p>\n<p>The <em>ServerRoot<\/em> directory indicates the main or root directory of the server. It is a symbolic link set as a trick in Tutorial 1. We\u2019ll make good use of this, because by reassigning this symbolic link we will be able to test a series of different compiled versions of Apache without having to change anything in the configuration file.<\/p>\n<p>We then assign the user and group to <em>User<\/em> and <em>Group<\/em>. This is a good idea, because we want to prevent the server from running as a root process. In fact, the master or parent process will be running as root, but the actual server or child processes and their threads will be running under the name defined here. The <em>www-data<\/em> user is the name normally used on Debian\/Ubuntu systems. Other distributions use different names. Make sure that the user name and associated group you choose are actually present on the system.<\/p>\n<p>The <em>PidFile<\/em> specifies the file that Apache writes its process ID number to. The path selected is the default. It is mentioned here so you don\u2019t have to look for this path in the documentation later on.<\/p>\n<p><em>ServerTokens<\/em> defines how the server identifies itself. Productive tokens are defined using <em>Prod<\/em>. This means that the server identifies itself only as <em>Apache<\/em> without the version number and loaded modules which is a bit more discreet. Let\u2019s not fool ourselves: The version of the server can be easily determined over the internet, but we still don\u2019t have to send it along as part of the sender for every communication.<\/p>\n<p><em>UseCanonicalName<\/em> tells the server which <em>host names<\/em> and <em>ports<\/em> to use when it has to write a link to itself. The <em>On<\/em> value defines that the <em>ServerName<\/em> is to be used. One alternative would be to use the host header sent by the client, which however we don\u2019t want in our setup.<\/p>\n<p>The <em>TraceEnable<\/em> directive prevents certain types of spying attacks on our setup. The HTTP <em>TRACE<\/em> method instructs the web server to return the requests it receives 1:1. This enables us to determine whether a proxy server is interposed and whether it has modified the request. This is no loss in our simple setup, but this information is better kept confidential on a corporate network. So, for the sake of security we are turning <em>TraceEnable<\/em> off by default.<\/p>\n<p>Broadly speaking, <em>Timeout<\/em> indicates the maximum time in seconds that may be used to process a request. In reality it is a bit more complicated, but we don\u2019t need to worry about the details at the moment. The default value of 60 seconds is very high. We\u2019ll lower it to 10 seconds.<\/p>\n<p><em>MaxRequestWorkers<\/em> is the maximum number of threads working in parallel to reply to requests. The default value is once again a bit high. Let\u2019s set it to 100. If this value is reached in production, then we have a lot of traffic.<\/p>\n<p>By default, the Apache server listens to any available URL on the internet. However, for our tests we will have it initially listen to only the <em>IPv4 local host<\/em> URL and on default HTTP port 80. It\u2019s possible to have multiple <em>Listen<\/em> directives one after the other, but having only one is sufficient for our purposes at the moment.<\/p>\n<p>Let\u2019s now load five modules:<\/p>\n<ul>\n<li>mpm_event_module : \u201cevent\u201d process model<\/li>\n<li>unixd_module : access to Unix user names and groups<\/li>\n<li>log_config_module : freely defined access log<\/li>\n<li>authn_core_module : core module for authentication<\/li>\n<li>authz_core_module : core module for authorization<\/li>\n<\/ul>\n<p>We already compiled all of the modules supplied by Apache in Tutorial 1. We will now be adding the most important ones to our configuration. <em>mpm_event_module<\/em> and <em>unixd_module<\/em> are needed to operate the server. When compiling in the first tutorial we chose the <em>event<\/em> process model, which we will now be enabling by loading the module. Of interest: In Apache 2.4 such a fundamental setting as the process model of the server can be set in the configuration. We need the <em>unixd<\/em> module to run the server (as described above) under the user name we defined.<\/p>\n<p><em>log_config_module<\/em> enables us to freely define the access log, which we will be making use of shortly. And finally, there are the two <em>authn_core_module<\/em> and <em>authz_core_module<\/em> modules. The first part of the name indicates authentication (<em>authn<\/em>) and authorization (<em>authz<\/em>). Core then means that these two modules are the basis for these functions.<\/p>\n<p>In terms of access security, we often hear about <em>AAA<\/em>, short for <em>authentication<\/em>, <em>authorization<\/em> and <em>access control<\/em>. Authentication means checking the identity of the user. Authorization means you define the access permissions for a user that has been authenticated. Finally, access control means the decision as to whether access is granted to an authenticated user with the access permissions defined for him. We lay the foundation for this mechanism by loading these two modules. There are a lot of other modules with the <em>authn<\/em> and <em>authz<\/em> prefixes which require these modules. For the moment we actually only need the authorization module, but by loading the authentication module we are preparing for extensions later on.<\/p>\n<p>We use <em>ErrorLogFormat<\/em> to change the format of the error log file. We will be extending the customary log format a bit by precisely defining the time stamp. <code>[%{cu}t]<\/code> will then produce entries such as <code>[2015-09-24 06:34:29.199635]<\/code>. This means the date written backwards, then the time with a precision of microseconds. Writing the date backwards makes it more easily sortable in the log file; the microseconds provide precise information as to the time of the entry and enable conclusions to be made about how long processing takes in the different modules. This is also the purpose of the next configuration part, <code>[%-m:%-l]<\/code>, that specifies the module doing the logging and the <em>log level<\/em>, i.e.\u00a0the severity of the error. After this come the IP address of the client (<code>%-a<\/code>), a unique identifier for the request (<code>%-L<\/code>) (a unique ID which can be used in later tutorials in correlation to requests) and the actual message, which we reference using <code>%M<\/code>.<\/p>\n<p>We use <em>LogFormat<\/em> to define a format for the access log file. We give it the name <em>combined<\/em>. This common format includes the client IP address, time stamp, methods, path, HTTP version, HTTP status code, response length, referer and the name of the browser (User-Agent). For the timestamp we are selecting a structure that is quite complicated. The reason for this is the desire to use the same format for timestamps as in the error log and access logs. While easy identification is available in the error log, we have to painstakingly put together the timestamp for the access log format.<\/p>\n<p>By using <em>debug<\/em> we are setting the <em>LogLevel<\/em> for the error log file to the highest level. This is too chatty for production, but it makes perfect sense in a lab-like setting. Apache is not very chatty in general so the volume of data is usually easy enough to handle.<\/p>\n<p>We assign the error log file by adding the path <em>logs\/error.log<\/em> to <em>ErrorLog<\/em>. This path is relative to the <em>ServerRoot<\/em> directory.<\/p>\n<p>We now use <em>LogFormat combined<\/em> for our access log file called <em>logs\/access.log<\/em>.<\/p>\n<p>The web server delivers files. It searches for them on a disk partition or generates them with help from an installed application. We are still using a simple case here and tell the server to look for the files in <em>DocumentRoot<\/em>. <em>\/apache\/htdocs<\/em> is an absolute path below <em>ServerRoot<\/em>. A relative path could be entered, but it\u2019s best to make things clear here! Specifically, <em>DocumentRoot<\/em> means that the URL path <em>\/<\/em> is being mapped to the <em>\/apache\/htdocs<\/em> operating system path.<\/p>\n<p>Now comes a <em>directory<\/em> block. We use this block to prevent files from being delivered outside the <em>DocumentRoot<\/em> we defined. We forbid any access to the \/ path using the <em>Require all denied<\/em> directive. This entry refers to the authentication (<em>all<\/em>), makes a statement about authorization (<em>Require<\/em>) and defines access: <em>denied<\/em>, i.e.\u00a0no access for anyone, at least to the <em>\/<\/em> directory.<\/p>\n<p>We set the <em>Options<\/em> directive to <em>SymLinksIfOwnerMatch<\/em>. We can use <em>Options<\/em> to define the special features to take into account when sending the \/ directory. Actually, none at all and that\u2019s why in production we would write Options <em>None<\/em>. But in our case we have set <em>DocumentRoot<\/em> to a symbolic link and it can only be searched for and found if we assign <em>SymLinksIfOwnerMatch<\/em> to the server, also allowing symlinks below \/. At least if the permissions are clear. For security reasons, on production systems it is best to not to rely on symlinks when serving files. But convenience still takes precedence on our test system.<\/p>\n<p>Let\u2019s now open up a <em>VirtualHost<\/em>. It corresponds to the <em>Listen<\/em> directive defined above. Together with the <em>Directory<\/em> block we just defined, it defines that by default our web server does not permit any access at all. However, we want to permit access to IP address <em>127.0.0.1, Port 80<\/em>, which is defined in this block.<\/p>\n<p>Specifically, we permit access to our <em>DocumentRoot<\/em>. The final instruction here is <em>Require all granted<\/em>, where unlike the <em>\/<\/em> directory we permit full access. Unlike above, from this path on no provision is made for symlinks or any special capabilities: <em>Options None<\/em>.<\/p>\n<h3 id=\"step-3-starting-the-server\">Step 3: Starting the server<\/h3>\n<p>Our minimal server has thus been described. It would be possible to define a server that is even more bare bones. It would however not be as comfortable to work with as ours and it wouldn\u2019t be any more secure. A certain amount of basic security is however advisable. This is because in the lab we are building a service which should then with specific adjustments be able to be put into a production environment. Wanting to secure a service from top to bottom right before entering a production environment is illusory.<\/p>\n<p>As we did in Tutorial 1 let\u2019s start the server in the foreground and not as a daemon:<\/p>\n<div class=\"sourceCode\" id=\"cb2\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\"><\/a>$<span class=\"op\">&gt;<\/span> <span class=\"bu\">cd<\/span> \/apache<\/span>\n<span id=\"cb2-3\"><a href=\"#cb2-3\" aria-hidden=\"true\"><\/a>$<span class=\"op\">&gt;<\/span> <span class=\"fu\">sudo<\/span> .\/bin\/httpd -X<\/span><\/code><\/pre><\/div>\n<h3 id=\"step-4-talking-to-the-server-using-curl\">Step 4: Talking to the server using curl<\/h3>\n<p>Now we can again communicate with the server from a web browser. But working in the shell at first can be more effective, making it easier to understand what is going on.<\/p>\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\"><\/a>$<span class=\"op\">&gt;<\/span> <span class=\"ex\">curl<\/span> http:\/\/localhost\/index.html<\/span><\/code><\/pre><\/div>\n<p>Returns the following:<\/p>\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb4-1\"><a href=\"#cb4-1\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span><span class=\"ex\">html<\/span><span class=\"op\">&gt;&lt;<\/span>body<span class=\"op\">&gt;&lt;<\/span>h1<span class=\"op\">&gt;<\/span>It works!<span class=\"op\">&lt;<\/span>\/h1<span class=\"op\">&gt;&lt;<\/span>\/body<span class=\"op\">&gt;&lt;<\/span>\/html<span class=\"op\">&gt;<\/span><\/span><\/code><\/pre><\/div>\n<p>We have thus sent an HTTP request and have received a response from our minimally configured server, meeting our expectations.<\/p>\n<h3 id=\"step-5-examining-requests-and-responses\">Step 5: Examining requests and responses<\/h3>\n<p>This is what happens during an HTTP request. But what exactly is the server saying to us? To find out, let\u2019s start <em>curl<\/em>. This time with the <em>verbose<\/em> option.<\/p>\n<div class=\"sourceCode\" id=\"cb5\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb5-1\"><a href=\"#cb5-1\" aria-hidden=\"true\"><\/a>$<span class=\"op\">&gt;<\/span> <span class=\"ex\">curl<\/span> --verbose http:\/\/localhost\/index.html<\/span>\n<span id=\"cb5-2\"><a href=\"#cb5-2\" aria-hidden=\"true\"><\/a><span class=\"ex\">*<\/span> Hostname was NOT found in DNS cache<\/span>\n<span id=\"cb5-3\"><a href=\"#cb5-3\" aria-hidden=\"true\"><\/a><span class=\"ex\">*<\/span>   Trying 127.0.0.1...<\/span>\n<span id=\"cb5-4\"><a href=\"#cb5-4\" aria-hidden=\"true\"><\/a><span class=\"ex\">*<\/span> Connected to localhost (127.0.0.1) <span class=\"ex\">port<\/span> 80 (#0)<\/span>\n<span id=\"cb5-5\"><a href=\"#cb5-5\" aria-hidden=\"true\"><\/a><span class=\"op\">&gt;<\/span> <span class=\"ex\">GET<\/span> \/index.html HTTP\/1.1<\/span>\n<span id=\"cb5-6\"><a href=\"#cb5-6\" aria-hidden=\"true\"><\/a><span class=\"op\">&gt;<\/span> <span class=\"ex\">User-Agent<\/span>: curl\/7.35.0<\/span>\n<span id=\"cb5-7\"><a href=\"#cb5-7\" aria-hidden=\"true\"><\/a><span class=\"op\">&gt;<\/span> <span class=\"ex\">Host<\/span>: localhost<\/span>\n<span id=\"cb5-8\"><a href=\"#cb5-8\" aria-hidden=\"true\"><\/a><span class=\"op\">&gt;<\/span> <span class=\"ex\">Accept<\/span>: *\/*<\/span>\n<span id=\"cb5-9\"><a href=\"#cb5-9\" aria-hidden=\"true\"><\/a><span class=\"op\">&gt;<\/span> <\/span>\n<span id=\"cb5-10\"><a href=\"#cb5-10\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">HTTP\/1.1<\/span> 200 OK<\/span>\n<span id=\"cb5-11\"><a href=\"#cb5-11\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">Date<\/span>: Thu, 24 Sep 2015 09:27:02 GMT<\/span>\n<span id=\"cb5-12\"><a href=\"#cb5-12\" aria-hidden=\"true\"><\/a><span class=\"ex\">*<\/span> Server Apache is not blacklisted<\/span>\n<span id=\"cb5-13\"><a href=\"#cb5-13\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">Server<\/span>: Apache<\/span>\n<span id=\"cb5-14\"><a href=\"#cb5-14\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">Last-Modified<\/span>: Mon, 11 Jun 2007 18:53:14 GMT<\/span>\n<span id=\"cb5-15\"><a href=\"#cb5-15\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">ETag<\/span>: <span class=\"st\">&quot;2d-432a5e4a73a80&quot;<\/span><\/span>\n<span id=\"cb5-16\"><a href=\"#cb5-16\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">Accept-Ranges<\/span>: bytes<\/span>\n<span id=\"cb5-17\"><a href=\"#cb5-17\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">Content-Length<\/span>: 45<\/span>\n<span id=\"cb5-18\"><a href=\"#cb5-18\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <\/span>\n<span id=\"cb5-19\"><a href=\"#cb5-19\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span><span class=\"ex\">html<\/span><span class=\"op\">&gt;&lt;<\/span>body<span class=\"op\">&gt;&lt;<\/span>h1<span class=\"op\">&gt;<\/span>It works!<span class=\"op\">&lt;<\/span>\/h1<span class=\"op\">&gt;&lt;<\/span>\/body<span class=\"op\">&gt;&lt;<\/span>\/html<span class=\"op\">&gt;<\/span><\/span>\n<span id=\"cb5-20\"><a href=\"#cb5-20\" aria-hidden=\"true\"><\/a><span class=\"ex\">*<\/span> Connection #0 to host localhost left intact<\/span><\/code><\/pre><\/div>\n<p>The lines marked with a asterisk (*) describe messages concerning opening and closing the connection. They do not reflect network traffic. The request follows &gt; and the response &lt;.<\/p>\n<p>Specifically, an HTTP request comprises 4 parts:<\/p>\n<ul>\n<li>Request line and request header<\/li>\n<li>Request body (optional and missing here for a GET request)<\/li>\n<li>Response header<\/li>\n<li>Response body<\/li>\n<\/ul>\n<p>We don\u2019t have to worry about the first parts just yet. It\u2019s the <em>response headers<\/em> that are interesting. This is the part used by the web server to describe the response. The actual response, the <em>response body<\/em>, follows after an empty line.<\/p>\n<p>In order, what do the headers mean?<\/p>\n<p>At first comes the <em>status<\/em> line including the <em>protocol<\/em>, the version, followed by the <em>status code<\/em>. <em>200 OK<\/em> is the normal response from a web server. On the next line we see the date and time of the server. The next line begins with an asterisk, _*_, signifying a line belonging to <em>curl<\/em>. The message is related to <em>curl\u2019s<\/em> handling of HTTP pipelining, which we don\u2019t have to concern ourselves with. Then comes the <em>server<\/em> line on which our Apache web server identifies itself. This is the shortest possible identification. We have defined it using <em>ServerTokens<\/em> Prod.<\/p>\n<p>The server will then tell us when the file the response is based on was last changed, i.e.\u00a0the <em>Unix modified timestamp<\/em>. <em>ETag<\/em> and <em>Accept<\/em> ranges don\u2019t require our attention for the moment. What\u2019s more interesting is <em>Content-Length<\/em>. This specifies how many bytes to expect in the <em>response body<\/em>. 45 bytes in our case.<\/p>\n<p>Incidentally, the order of these headers is characteristic for web servers. <em>NginX<\/em> uses a different order and, for instance, puts the <em>server header<\/em> in front of the date. Apache can still be identified even if the server line is intended to be misleading.<\/p>\n<h3 id=\"step-6-examining-the-response-a-bit-more-closely\">Step 6: Examining the response a bit more closely<\/h3>\n<p>During communication it is possible to get a somewhat more detailed view in <em>curl<\/em>. We use the <em>\u2013trace-ascii<\/em> command line parameter to do this:<\/p>\n<div class=\"sourceCode\" id=\"cb6\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb6-1\"><a href=\"#cb6-1\" aria-hidden=\"true\"><\/a>$<span class=\"op\">&gt;<\/span> <span class=\"ex\">curl<\/span> http:\/\/localhost\/index.html --data <span class=\"st\">&quot;foo=bar&quot;<\/span> --trace-ascii -<\/span>\n<span id=\"cb6-2\"><a href=\"#cb6-2\" aria-hidden=\"true\"><\/a>== <span class=\"ex\">Info<\/span>: Hostname was NOT found in DNS cache<\/span>\n<span id=\"cb6-3\"><a href=\"#cb6-3\" aria-hidden=\"true\"><\/a>== <span class=\"ex\">Info<\/span>:   Trying 127.0.0.1...<\/span>\n<span id=\"cb6-4\"><a href=\"#cb6-4\" aria-hidden=\"true\"><\/a>== <span class=\"ex\">Info<\/span>: Connected to localhost (127.0.0.1) <span class=\"ex\">port<\/span> 80 (#0)<\/span>\n<span id=\"cb6-5\"><a href=\"#cb6-5\" aria-hidden=\"true\"><\/a>=<span class=\"op\">&gt;<\/span> <span class=\"ex\">Send<\/span> header, 83 bytes (0x53)<\/span>\n<span id=\"cb6-6\"><a href=\"#cb6-6\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: GET \/index.html HTTP\/1.1<\/span>\n<span id=\"cb6-7\"><a href=\"#cb6-7\" aria-hidden=\"true\"><\/a><span class=\"ex\">0033<\/span>: Host: localhost<\/span>\n<span id=\"cb6-8\"><a href=\"#cb6-8\" aria-hidden=\"true\"><\/a><span class=\"ex\">001a<\/span>: User-Agent: curl\/7.71.1<\/span>\n<span id=\"cb6-9\"><a href=\"#cb6-9\" aria-hidden=\"true\"><\/a><span class=\"ex\">0044<\/span>: Accept: *\/*<\/span>\n<span id=\"cb6-10\"><a href=\"#cb6-10\" aria-hidden=\"true\"><\/a><span class=\"ex\">0052<\/span>: Content-Length: 7<\/span>\n<span id=\"cb6-11\"><a href=\"#cb6-11\" aria-hidden=\"true\"><\/a><span class=\"ex\">0065<\/span>: Content-Type: application\/x-www-form-urlencoded<\/span>\n<span id=\"cb6-12\"><a href=\"#cb6-12\" aria-hidden=\"true\"><\/a><span class=\"ex\">0096<\/span>:<\/span>\n<span id=\"cb6-13\"><a href=\"#cb6-13\" aria-hidden=\"true\"><\/a>=<span class=\"op\">&gt;<\/span> <span class=\"ex\">Send<\/span> data, 7 bytes (0x7)<\/span>\n<span id=\"cb6-14\"><a href=\"#cb6-14\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: foo=bar<\/span>\n<span id=\"cb6-15\"><a href=\"#cb6-15\" aria-hidden=\"true\"><\/a>== <span class=\"ex\">Info<\/span>: upload completely sent off: 7 out of 7 bytes<\/span>\n<span id=\"cb6-16\"><a href=\"#cb6-16\" aria-hidden=\"true\"><\/a>== <span class=\"ex\">Info<\/span>: Mark bundle as not supporting multiuse<\/span>\n<span id=\"cb6-17\"><a href=\"#cb6-17\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>= <span class=\"ex\">Recv<\/span> header, 17 bytes (0x11)<\/span>\n<span id=\"cb6-18\"><a href=\"#cb6-18\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: HTTP\/1.1 200 OK<\/span>\n<span id=\"cb6-19\"><a href=\"#cb6-19\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>= <span class=\"ex\">Recv<\/span> header, 37 bytes (0x25)<\/span>\n<span id=\"cb6-20\"><a href=\"#cb6-20\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: Date: Thu, 24 Sep 2015 11:46:17 GMT<\/span>\n<span id=\"cb6-21\"><a href=\"#cb6-21\" aria-hidden=\"true\"><\/a>== <span class=\"ex\">Info<\/span>: Server Apache is not blacklisted<\/span>\n<span id=\"cb6-22\"><a href=\"#cb6-22\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>= <span class=\"ex\">Recv<\/span> header, 16 bytes (0x10)<\/span>\n<span id=\"cb6-23\"><a href=\"#cb6-23\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: Server: Apache<\/span>\n<span id=\"cb6-24\"><a href=\"#cb6-24\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>= <span class=\"ex\">Recv<\/span> header, 46 bytes (0x2e)<\/span>\n<span id=\"cb6-25\"><a href=\"#cb6-25\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT<\/span>\n<span id=\"cb6-26\"><a href=\"#cb6-26\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>= <span class=\"ex\">Recv<\/span> header, 26 bytes (0x1a)<\/span>\n<span id=\"cb6-27\"><a href=\"#cb6-27\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: ETag: <span class=\"st\">&quot;2d-432a5e4a73a80&quot;<\/span><\/span>\n<span id=\"cb6-28\"><a href=\"#cb6-28\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>= <span class=\"ex\">Recv<\/span> header, 22 bytes (0x16)<\/span>\n<span id=\"cb6-29\"><a href=\"#cb6-29\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: Accept-Ranges: bytes<\/span>\n<span id=\"cb6-30\"><a href=\"#cb6-30\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>= <span class=\"ex\">Recv<\/span> header, 20 bytes (0x14)<\/span>\n<span id=\"cb6-31\"><a href=\"#cb6-31\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: Content-Length: 45<\/span>\n<span id=\"cb6-32\"><a href=\"#cb6-32\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>= <span class=\"ex\">Recv<\/span> header, 2 bytes (0x2)<\/span>\n<span id=\"cb6-33\"><a href=\"#cb6-33\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: <\/span>\n<span id=\"cb6-34\"><a href=\"#cb6-34\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span>= <span class=\"ex\">Recv<\/span> data, 45 bytes (0x2d)<\/span>\n<span id=\"cb6-35\"><a href=\"#cb6-35\" aria-hidden=\"true\"><\/a><span class=\"ex\">0000<\/span>: <span class=\"op\">&lt;<\/span>html<span class=\"op\">&gt;&lt;<\/span>body<span class=\"op\">&gt;&lt;<\/span>h1<span class=\"op\">&gt;<\/span>It works!<span class=\"op\">&lt;<\/span>\/h1<span class=\"op\">&gt;&lt;<\/span>\/body<span class=\"op\">&gt;&lt;<\/span>\/html<span class=\"op\">&gt;<\/span>.<\/span>\n<span id=\"cb6-36\"><a href=\"#cb6-36\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span><span class=\"ex\">html<\/span><span class=\"op\">&gt;&lt;<\/span>body<span class=\"op\">&gt;&lt;<\/span>h1<span class=\"op\">&gt;<\/span>It works!<span class=\"op\">&lt;<\/span>\/h1<span class=\"op\">&gt;&lt;<\/span>\/body<span class=\"op\">&gt;&lt;<\/span>\/html<span class=\"op\">&gt;<\/span><\/span>\n<span id=\"cb6-37\"><a href=\"#cb6-37\" aria-hidden=\"true\"><\/a>== <span class=\"ex\">Info<\/span>: Connection #0 to host localhost left intact<\/span><\/code><\/pre><\/div>\n<p><em>\u2013trace-ascii<\/em> requires a file as a parameter in order to make an <em>ASCII dump<\/em> of communication in it. \u201c-\u201d works as a shortcut for <em>STDOUT<\/em>, enabling us to easily see what is being logged.<\/p>\n<p>Compared to <em>verbose<\/em>, <em>trace-ascii<\/em> also shows the request body and it provides more details about the number of transferred bytes in the <em>request<\/em> and <em>response<\/em> phase. The request headers in the example above are thus 83 bytes. The bytes are then listed for each header in the response and overall for the body in the response: 45 bytes. This may seem like we are splitting hairs. But in fact, it can be crucial when something is missing and it is not quite certain what or where in the sequence it was delivered. Thus, it\u2019s worth noting that 2 bytes are added to each header line. These are the CR (carriage returns) and NL (new lines) in the header lines included in the HTTP protocol. In the response body, on the other hand, only the actual content of the file is returned. This is obviously only one NL without CR here. On the third to last line (<em>000: &lt;html \u2026<\/em>) a point comes after the greater than character This is code for the NL character in the response, which like other escape sequences is output in the form of a point.<\/p>\n<h3 id=\"step-7-working-with-the-trace-method\">Step 7: Working with the trace method<\/h3>\n<p>The <em>TraceEnable<\/em> directive was described above. We have turned it <em>off<\/em> as a precaution. It can however be very useful in debugging. So, let\u2019s give it a try. Let\u2019s set the option to on:<\/p>\n<div class=\"sourceCode\" id=\"cb7\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb7-1\"><a href=\"#cb7-1\" aria-hidden=\"true\"><\/a><span class=\"ex\">TraceEnable<\/span> On<\/span><\/code><\/pre><\/div>\n<p>We restart the server and make the following curl request:<\/p>\n<div class=\"sourceCode\" id=\"cb8\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb8-1\"><a href=\"#cb8-1\" aria-hidden=\"true\"><\/a>$<span class=\"op\">&gt;<\/span> <span class=\"ex\">curl<\/span> -v --request TRACE http:\/\/localhost\/index.html<\/span><\/code><\/pre><\/div>\n<p>We are thus accessing the known <em>URL<\/em> using the <em>HTTP TRACE method<\/em> (in place of <em>GET<\/em>). We expect the following as the result:<\/p>\n<div class=\"sourceCode\" id=\"cb9\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb9-1\"><a href=\"#cb9-1\" aria-hidden=\"true\"><\/a><span class=\"ex\">*<\/span> Hostname was NOT found in DNS cache<\/span>\n<span id=\"cb9-2\"><a href=\"#cb9-2\" aria-hidden=\"true\"><\/a><span class=\"ex\">*<\/span>  Trying 127.0.0.1...<\/span>\n<span id=\"cb9-3\"><a href=\"#cb9-3\" aria-hidden=\"true\"><\/a><span class=\"ex\">*<\/span> Connected to localhost (127.0.0.1) <span class=\"ex\">port<\/span> 80 (#0)<\/span>\n<span id=\"cb9-4\"><a href=\"#cb9-4\" aria-hidden=\"true\"><\/a><span class=\"op\">&gt;<\/span> <span class=\"ex\">TRACE<\/span> \/index.html HTTP\/1.1<\/span>\n<span id=\"cb9-5\"><a href=\"#cb9-5\" aria-hidden=\"true\"><\/a><span class=\"op\">&gt;<\/span> <span class=\"ex\">User-Agent<\/span>: curl\/7.35.0<\/span>\n<span id=\"cb9-6\"><a href=\"#cb9-6\" aria-hidden=\"true\"><\/a><span class=\"op\">&gt;<\/span> <span class=\"ex\">Host<\/span>: localhost<\/span>\n<span id=\"cb9-7\"><a href=\"#cb9-7\" aria-hidden=\"true\"><\/a><span class=\"op\">&gt;<\/span> <span class=\"ex\">Accept<\/span>: *\/*<\/span>\n<span id=\"cb9-8\"><a href=\"#cb9-8\" aria-hidden=\"true\"><\/a><span class=\"op\">&gt;<\/span> <\/span>\n<span id=\"cb9-9\"><a href=\"#cb9-9\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">HTTP\/1.1<\/span> 200 OK<\/span>\n<span id=\"cb9-10\"><a href=\"#cb9-10\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">Date<\/span>: Thu, 24 Sep 2015 09:38:01 GMT<\/span>\n<span id=\"cb9-11\"><a href=\"#cb9-11\" aria-hidden=\"true\"><\/a><span class=\"ex\">*<\/span> Server Apache is not blacklisted<\/span>\n<span id=\"cb9-12\"><a href=\"#cb9-12\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">Server<\/span>: Apache<\/span>\n<span id=\"cb9-13\"><a href=\"#cb9-13\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">Transfer-Encoding<\/span>: chunked<\/span>\n<span id=\"cb9-14\"><a href=\"#cb9-14\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <span class=\"ex\">Content-Type<\/span>: message\/http<\/span>\n<span id=\"cb9-15\"><a href=\"#cb9-15\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span> <\/span>\n<span id=\"cb9-16\"><a href=\"#cb9-16\" aria-hidden=\"true\"><\/a><span class=\"ex\">TRACE<\/span> \/index.html HTTP\/1.1<\/span>\n<span id=\"cb9-17\"><a href=\"#cb9-17\" aria-hidden=\"true\"><\/a><span class=\"ex\">User-Agent<\/span>: curl\/7.35.0<\/span>\n<span id=\"cb9-18\"><a href=\"#cb9-18\" aria-hidden=\"true\"><\/a><span class=\"ex\">Host<\/span>: localhost<\/span>\n<span id=\"cb9-19\"><a href=\"#cb9-19\" aria-hidden=\"true\"><\/a><span class=\"ex\">Accept<\/span>: *\/*<\/span>\n<span id=\"cb9-20\"><a href=\"#cb9-20\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb9-21\"><a href=\"#cb9-21\" aria-hidden=\"true\"><\/a><span class=\"ex\">*<\/span> Connection #0 to host localhost left intact<\/span><\/code><\/pre><\/div>\n<p>In the <em>body<\/em> the server repeats the information about the request sent to it as intended. In fact, the lines are identical here. We are thus able to confirm that nothing has happened to the request in transit. If however we had passed through one or more interposed proxy servers, then there would be additional <em>header<\/em> lines that we would also be able to see as a <em>client<\/em>. At a later point we will become familiar with more powerful tools for debugging. Nevertheless, we don\u2019t want to completely ignore the <em>TRACE<\/em> method.<\/p>\n<p>Don\u2019t forget to turn <em>TraceEnable<\/em> off again.<\/p>\n<h3 id=\"step-8-using-ab-to-test-the-server\">Step 8: Using \u201cab\u201d to test the server<\/h3>\n<p>So much for the simple server. But just for fun we can put it to the test. We\u2019ll perform a small performance test using <em>ab<\/em>, short for <em>ApacheBench<\/em>. This is a very simple benchmarking program that is always at hand and able to quickly give you initial performance results. I like to run it before and after a configuration change to get an idea about whether anything in terms of performance has changed. <em>ab<\/em> is very powerful and calling it locally does not give you clean results. But you can get an initial impression using this tool.<\/p>\n<div class=\"sourceCode\" id=\"cb10\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb10-1\"><a href=\"#cb10-1\" aria-hidden=\"true\"><\/a>$<span class=\"op\">&gt;<\/span> <span class=\"ex\">.\/bin\/ab<\/span> -c 1 -n 1000 http:\/\/localhost\/index.html<\/span><\/code><\/pre><\/div>\n<p>We are starting ab using <em>concurrency 1<\/em>. The means that we are executing only one request at a time. In total, we will be executing 1,000 requests from the known <em>URL<\/em>. This is the output from <em>ab<\/em>:<\/p>\n<div class=\"sourceCode\" id=\"cb11\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb11-1\"><a href=\"#cb11-1\" aria-hidden=\"true\"><\/a>$<span class=\"op\">&gt;<\/span> <span class=\"ex\">.\/bin\/ab<\/span> -c 1 -n 1000 http:\/\/localhost\/index.html<\/span>\n<span id=\"cb11-2\"><a href=\"#cb11-2\" aria-hidden=\"true\"><\/a><span class=\"ex\">This<\/span> is ApacheBench, Version 2.3 <span class=\"op\">&lt;<\/span><span class=\"va\">$Revision<\/span>: 1663405 $<span class=\"op\">&gt;<\/span><\/span>\n<span id=\"cb11-3\"><a href=\"#cb11-3\" aria-hidden=\"true\"><\/a><span class=\"ex\">Copyright<\/span> 1996 Adam Twiss, Zeus Technology Ltd, http:\/\/www.zeustech.net\/<\/span>\n<span id=\"cb11-4\"><a href=\"#cb11-4\" aria-hidden=\"true\"><\/a><span class=\"ex\">Licensed<\/span> to The Apache Software Foundation, http:\/\/www.apache.org\/<\/span>\n<span id=\"cb11-5\"><a href=\"#cb11-5\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb11-6\"><a href=\"#cb11-6\" aria-hidden=\"true\"><\/a><span class=\"ex\">Benchmarking<\/span> localhost (be patient)<\/span>\n<span id=\"cb11-7\"><a href=\"#cb11-7\" aria-hidden=\"true\"><\/a><span class=\"ex\">Completed<\/span> 100 requests<\/span>\n<span id=\"cb11-8\"><a href=\"#cb11-8\" aria-hidden=\"true\"><\/a><span class=\"ex\">Completed<\/span> 200 requests<\/span>\n<span id=\"cb11-9\"><a href=\"#cb11-9\" aria-hidden=\"true\"><\/a><span class=\"ex\">Completed<\/span> 300 requests<\/span>\n<span id=\"cb11-10\"><a href=\"#cb11-10\" aria-hidden=\"true\"><\/a><span class=\"ex\">Completed<\/span> 400 requests<\/span>\n<span id=\"cb11-11\"><a href=\"#cb11-11\" aria-hidden=\"true\"><\/a><span class=\"ex\">Completed<\/span> 500 requests<\/span>\n<span id=\"cb11-12\"><a href=\"#cb11-12\" aria-hidden=\"true\"><\/a><span class=\"ex\">Completed<\/span> 600 requests<\/span>\n<span id=\"cb11-13\"><a href=\"#cb11-13\" aria-hidden=\"true\"><\/a><span class=\"ex\">Completed<\/span> 700 requests<\/span>\n<span id=\"cb11-14\"><a href=\"#cb11-14\" aria-hidden=\"true\"><\/a><span class=\"ex\">Completed<\/span> 800 requests<\/span>\n<span id=\"cb11-15\"><a href=\"#cb11-15\" aria-hidden=\"true\"><\/a><span class=\"ex\">Completed<\/span> 900 requests<\/span>\n<span id=\"cb11-16\"><a href=\"#cb11-16\" aria-hidden=\"true\"><\/a><span class=\"ex\">Completed<\/span> 1000 requests<\/span>\n<span id=\"cb11-17\"><a href=\"#cb11-17\" aria-hidden=\"true\"><\/a><span class=\"ex\">Finished<\/span> 1000 requests<\/span>\n<span id=\"cb11-18\"><a href=\"#cb11-18\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb11-19\"><a href=\"#cb11-19\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb11-20\"><a href=\"#cb11-20\" aria-hidden=\"true\"><\/a><span class=\"ex\">Server<\/span> Software:        Apache<\/span>\n<span id=\"cb11-21\"><a href=\"#cb11-21\" aria-hidden=\"true\"><\/a><span class=\"ex\">Server<\/span> Hostname:        localhost<\/span>\n<span id=\"cb11-22\"><a href=\"#cb11-22\" aria-hidden=\"true\"><\/a><span class=\"ex\">Server<\/span> Port:            80<\/span>\n<span id=\"cb11-23\"><a href=\"#cb11-23\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb11-24\"><a href=\"#cb11-24\" aria-hidden=\"true\"><\/a><span class=\"ex\">Document<\/span> Path:          \/index.html<\/span>\n<span id=\"cb11-25\"><a href=\"#cb11-25\" aria-hidden=\"true\"><\/a><span class=\"ex\">Document<\/span> Length:        45 bytes<\/span>\n<span id=\"cb11-26\"><a href=\"#cb11-26\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb11-27\"><a href=\"#cb11-27\" aria-hidden=\"true\"><\/a><span class=\"ex\">Concurrency<\/span> Level:      1<\/span>\n<span id=\"cb11-28\"><a href=\"#cb11-28\" aria-hidden=\"true\"><\/a><span class=\"ex\">Time<\/span> taken for tests:   0.676 seconds<\/span>\n<span id=\"cb11-29\"><a href=\"#cb11-29\" aria-hidden=\"true\"><\/a><span class=\"ex\">Complete<\/span> requests:      1000<\/span>\n<span id=\"cb11-30\"><a href=\"#cb11-30\" aria-hidden=\"true\"><\/a><span class=\"ex\">Failed<\/span> requests:        0<\/span>\n<span id=\"cb11-31\"><a href=\"#cb11-31\" aria-hidden=\"true\"><\/a><span class=\"ex\">Total<\/span> transferred:      250000 bytes<\/span>\n<span id=\"cb11-32\"><a href=\"#cb11-32\" aria-hidden=\"true\"><\/a><span class=\"ex\">HTML<\/span> transferred:       45000 bytes<\/span>\n<span id=\"cb11-33\"><a href=\"#cb11-33\" aria-hidden=\"true\"><\/a><span class=\"ex\">Requests<\/span> per second:    1480.14 [#\/sec] (mean)<\/span>\n<span id=\"cb11-34\"><a href=\"#cb11-34\" aria-hidden=\"true\"><\/a><span class=\"ex\">Time<\/span> per request:       0.676 [ms] (mean)<\/span>\n<span id=\"cb11-35\"><a href=\"#cb11-35\" aria-hidden=\"true\"><\/a><span class=\"ex\">Time<\/span> per request:       0.676 [ms] (mean, across all concurrent requests)<\/span>\n<span id=\"cb11-36\"><a href=\"#cb11-36\" aria-hidden=\"true\"><\/a><span class=\"ex\">Transfer<\/span> rate:          361.36 [Kbytes\/sec] received<\/span>\n<span id=\"cb11-37\"><a href=\"#cb11-37\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb11-38\"><a href=\"#cb11-38\" aria-hidden=\"true\"><\/a><span class=\"ex\">Connection<\/span> Times (ms)<\/span>\n<span id=\"cb11-39\"><a href=\"#cb11-39\" aria-hidden=\"true\"><\/a>              <span class=\"ex\">min<\/span>  mean[+\/-sd] median   max<\/span>\n<span id=\"cb11-40\"><a href=\"#cb11-40\" aria-hidden=\"true\"><\/a><span class=\"ex\">Connect<\/span>:        0    0   0.0      0       0<\/span>\n<span id=\"cb11-41\"><a href=\"#cb11-41\" aria-hidden=\"true\"><\/a><span class=\"ex\">Processing<\/span>:     0    1   0.2      1       3<\/span>\n<span id=\"cb11-42\"><a href=\"#cb11-42\" aria-hidden=\"true\"><\/a><span class=\"ex\">Waiting<\/span>:        0    0   0.1      0       2<\/span>\n<span id=\"cb11-43\"><a href=\"#cb11-43\" aria-hidden=\"true\"><\/a><span class=\"ex\">Total<\/span>:          0    1   0.2      1       3<\/span>\n<span id=\"cb11-44\"><a href=\"#cb11-44\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb11-45\"><a href=\"#cb11-45\" aria-hidden=\"true\"><\/a><span class=\"ex\">Percentage<\/span> of the requests served within a certain time (ms)<\/span>\n<span id=\"cb11-46\"><a href=\"#cb11-46\" aria-hidden=\"true\"><\/a>  <span class=\"ex\">50%<\/span>      1<\/span>\n<span id=\"cb11-47\"><a href=\"#cb11-47\" aria-hidden=\"true\"><\/a>  <span class=\"ex\">66%<\/span>      1<\/span>\n<span id=\"cb11-48\"><a href=\"#cb11-48\" aria-hidden=\"true\"><\/a>  <span class=\"ex\">75%<\/span>      1<\/span>\n<span id=\"cb11-49\"><a href=\"#cb11-49\" aria-hidden=\"true\"><\/a>  <span class=\"ex\">80%<\/span>      1<\/span>\n<span id=\"cb11-50\"><a href=\"#cb11-50\" aria-hidden=\"true\"><\/a>  <span class=\"ex\">90%<\/span>      1<\/span>\n<span id=\"cb11-51\"><a href=\"#cb11-51\" aria-hidden=\"true\"><\/a>  <span class=\"ex\">95%<\/span>      1<\/span>\n<span id=\"cb11-52\"><a href=\"#cb11-52\" aria-hidden=\"true\"><\/a>  <span class=\"ex\">98%<\/span>      1<\/span>\n<span id=\"cb11-53\"><a href=\"#cb11-53\" aria-hidden=\"true\"><\/a>  <span class=\"ex\">99%<\/span>      1<\/span>\n<span id=\"cb11-54\"><a href=\"#cb11-54\" aria-hidden=\"true\"><\/a> <span class=\"ex\">100%<\/span>      3 (longest request)<\/span><\/code><\/pre><\/div>\n<p>What\u2019s of primary interest to us is the number of errors (<em>Failed requests<\/em>) and the number of requests per second (<em>Requests per second<\/em>). A value above one thousand is a good start. Especially considering that we are still working with a single process and not a parallelized daemon (which is also why the <em>concurrency level<\/em> is set to 1).<\/p>\n<h3 id=\"step-9-goodie-viewing-directives-and-modules\">Step 9 (Goodie): Viewing directives and modules<\/h3>\n<p>At the end of this tutorial we are going to be looking at a variety of directives, which an Apache web server started with our configuration file is familiar with, The different loaded modules extend the server\u2019s set of commands. The available configuration parameters are well documented on the Apache Project\u2019s website. In fact, in special cases it can however be helpful to get an overview of the directives made available from the loaded modules. You can get the directives by using the command line flag <em>-L<\/em>.<\/p>\n<div class=\"sourceCode\" id=\"cb12\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb12-1\"><a href=\"#cb12-1\" aria-hidden=\"true\"><\/a>$<span class=\"op\">&gt;<\/span> <span class=\"ex\">.\/bin\/httpd<\/span> -L<\/span>\n<span id=\"cb12-2\"><a href=\"#cb12-2\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span><span class=\"ex\">Directory<\/span> (core.c)<\/span>\n<span id=\"cb12-3\"><a href=\"#cb12-3\" aria-hidden=\"true\"><\/a>    <span class=\"ex\">Container<\/span> for directives affecting resources located in the specified directories<\/span>\n<span id=\"cb12-4\"><a href=\"#cb12-4\" aria-hidden=\"true\"><\/a>    <span class=\"ex\">Allowed<\/span> in *.conf only outside <span class=\"op\">&lt;<\/span>Directory<span class=\"op\">&gt;<\/span>, <span class=\"op\">&lt;<\/span>Files<span class=\"op\">&gt;<\/span>, <span class=\"op\">&lt;<\/span>Location<span class=\"op\">&gt;<\/span>, or <span class=\"op\">&lt;<\/span>If<span class=\"op\">&gt;<\/span><\/span>\n<span id=\"cb12-5\"><a href=\"#cb12-5\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span><span class=\"ex\">Location<\/span> (core.c)<\/span>\n<span id=\"cb12-6\"><a href=\"#cb12-6\" aria-hidden=\"true\"><\/a>    <span class=\"ex\">Container<\/span> for directives affecting resources accessed through the specified URL paths<\/span>\n<span id=\"cb12-7\"><a href=\"#cb12-7\" aria-hidden=\"true\"><\/a>    <span class=\"ex\">Allowed<\/span> in *.conf only outside <span class=\"op\">&lt;<\/span>Directory<span class=\"op\">&gt;<\/span>, <span class=\"op\">&lt;<\/span>Files<span class=\"op\">&gt;<\/span>, <span class=\"op\">&lt;<\/span>Location<span class=\"op\">&gt;<\/span>, or <span class=\"op\">&lt;<\/span>If<span class=\"op\">&gt;<\/span><\/span>\n<span id=\"cb12-8\"><a href=\"#cb12-8\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span><span class=\"ex\">VirtualHost<\/span> (core.c)<\/span>\n<span id=\"cb12-9\"><a href=\"#cb12-9\" aria-hidden=\"true\"><\/a>    <span class=\"ex\">Container<\/span> to map directives to a particular virtual host, takes one or more host addresses<\/span>\n<span id=\"cb12-10\"><a href=\"#cb12-10\" aria-hidden=\"true\"><\/a>    <span class=\"ex\">Allowed<\/span> in *.conf only outside <span class=\"op\">&lt;<\/span>Directory<span class=\"op\">&gt;<\/span>, <span class=\"op\">&lt;<\/span>Files<span class=\"op\">&gt;<\/span>, <span class=\"op\">&lt;<\/span>Location<span class=\"op\">&gt;<\/span>, or <span class=\"op\">&lt;<\/span>If<span class=\"op\">&gt;<\/span><\/span>\n<span id=\"cb12-11\"><a href=\"#cb12-11\" aria-hidden=\"true\"><\/a><span class=\"op\">&lt;<\/span><span class=\"ex\">Files<\/span> (core.c)<\/span>\n<span id=\"cb12-12\"><a href=\"#cb12-12\" aria-hidden=\"true\"><\/a><span class=\"ex\">...<\/span><\/span><\/code><\/pre><\/div>\n<p>The directives follow the order in which they are loaded. A brief description of its function comes after each directive.<\/p>\n<p>Using this list it is now possible to determine whether all of the modules loaded in the configuration, referenced respectively, are actually required. In complicated configurations with a large number of loaded modules it may happen that you are unsure whether all of the modules are actually being used.<\/p>\n<p>You can thus get the modules by reading the configuration file, the output of <em>httpd -L<\/em> summarized for each module and then look in the configuration file to see if any of the directives listed are being used. This nested manner of sending requests demands a find touch, but is one that I can highly recommend. Personally, I have solved it as follows:<\/p>\n<div class=\"sourceCode\" id=\"cb13\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb13-1\"><a href=\"#cb13-1\" aria-hidden=\"true\"><\/a>$<span class=\"op\">&gt;<\/span> <span class=\"fu\">grep<\/span> LoadModule conf\/httpd.conf <span class=\"kw\">|<\/span> <span class=\"fu\">awk<\/span> <span class=\"st\">&#39;{print $2}&#39;<\/span> <span class=\"kw\">|<\/span> <span class=\"fu\">sed<\/span> -e <span class=\"st\">&quot;s\/_module\/\/&quot;<\/span> <span class=\"kw\">|<\/span> <span class=\"kw\">while<\/span> <span class=\"bu\">read<\/span> <span class=\"va\">M<\/span>; <span class=\"kw\">do<\/span> <span class=\"kw\">\\<\/span><\/span>\n<span id=\"cb13-2\"><a href=\"#cb13-2\" aria-hidden=\"true\"><\/a>  <span class=\"bu\">echo<\/span> <span class=\"st\">&quot;Module <\/span><span class=\"va\">$M<\/span><span class=\"st\">&quot;<\/span><span class=\"kw\">;<\/span> <span class=\"va\">R=$(<\/span><span class=\"ex\">.\/bin\/httpd<\/span> -L <span class=\"kw\">|<\/span> <span class=\"fu\">grep<\/span> <span class=\"va\">$M<\/span> <span class=\"kw\">|<\/span> <span class=\"fu\">cut<\/span> -d<span class=\"dt\">\\ <\/span> -f1 <span class=\"kw\">|<\/span> <span class=\"fu\">tr<\/span> -d <span class=\"st\">&quot;&lt;&quot;<\/span> <span class=\"kw\">|<\/span> <span class=\"fu\">xargs<\/span> <span class=\"kw\">|<\/span> <span class=\"fu\">tr<\/span> <span class=\"st\">&quot; &quot;<\/span> <span class=\"st\">&quot;|&quot;<\/span><span class=\"va\">)<\/span>; <span class=\"kw\">\\<\/span><\/span>\n<span id=\"cb13-3\"><a href=\"#cb13-3\" aria-hidden=\"true\"><\/a>  <span class=\"fu\">egrep<\/span> -q <span class=\"st\">&quot;<\/span><span class=\"va\">$R<\/span><span class=\"st\">&quot;<\/span> .\/conf\/httpd.conf<span class=\"kw\">;<\/span> <span class=\"kw\">\\<\/span><\/span>\n<span id=\"cb13-4\"><a href=\"#cb13-4\" aria-hidden=\"true\"><\/a>  <span class=\"kw\">if<\/span><span class=\"bu\"> [<\/span> <span class=\"va\">$?<\/span> <span class=\"ot\">-eq<\/span> 0<span class=\"bu\"> ]<\/span>; <span class=\"kw\">then<\/span> <span class=\"bu\">echo<\/span> <span class=\"st\">&quot;OK&quot;<\/span><span class=\"kw\">;<\/span> <span class=\"kw\">else<\/span> <span class=\"bu\">echo<\/span> <span class=\"st\">&quot;Not used&quot;<\/span><span class=\"kw\">;<\/span> <span class=\"kw\">fi<\/span>; <span class=\"bu\">echo<\/span><span class=\"kw\">;<\/span> <span class=\"kw\">\\<\/span><\/span>\n<span id=\"cb13-5\"><a href=\"#cb13-5\" aria-hidden=\"true\"><\/a>  <span class=\"kw\">done<\/span><\/span>\n<span id=\"cb13-6\"><a href=\"#cb13-6\" aria-hidden=\"true\"><\/a><span class=\"ex\">Module<\/span> mpm_event<\/span>\n<span id=\"cb13-7\"><a href=\"#cb13-7\" aria-hidden=\"true\"><\/a><span class=\"ex\">OK<\/span><\/span>\n<span id=\"cb13-8\"><a href=\"#cb13-8\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb13-9\"><a href=\"#cb13-9\" aria-hidden=\"true\"><\/a><span class=\"ex\">Module<\/span> unixd<\/span>\n<span id=\"cb13-10\"><a href=\"#cb13-10\" aria-hidden=\"true\"><\/a><span class=\"ex\">OK<\/span><\/span>\n<span id=\"cb13-11\"><a href=\"#cb13-11\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb13-12\"><a href=\"#cb13-12\" aria-hidden=\"true\"><\/a><span class=\"ex\">Module<\/span> log_config<\/span>\n<span id=\"cb13-13\"><a href=\"#cb13-13\" aria-hidden=\"true\"><\/a><span class=\"ex\">OK<\/span><\/span>\n<span id=\"cb13-14\"><a href=\"#cb13-14\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb13-15\"><a href=\"#cb13-15\" aria-hidden=\"true\"><\/a><span class=\"ex\">Module<\/span> authn_core<\/span>\n<span id=\"cb13-16\"><a href=\"#cb13-16\" aria-hidden=\"true\"><\/a><span class=\"ex\">Not<\/span> used<\/span>\n<span id=\"cb13-17\"><a href=\"#cb13-17\" aria-hidden=\"true\"><\/a><\/span>\n<span id=\"cb13-18\"><a href=\"#cb13-18\" aria-hidden=\"true\"><\/a><span class=\"ex\">Module<\/span> authz_core<\/span>\n<span id=\"cb13-19\"><a href=\"#cb13-19\" aria-hidden=\"true\"><\/a><span class=\"ex\">OK<\/span><\/span><\/code><\/pre><\/div>\n<p>The <em>authn_core<\/em> module is thus not being used. This is correct, we described it as such above, since it is being loaded for use in the future. The rest of the modules appear to be needed.<\/p>\n<p>So much for this tutorial. You now have a capable server you can work with. We will continue to extend it in subsequent tutorials.<\/p>\n<h3 id=\"references\">References<\/h3>\n<ul>\n<li>Apache: http:\/\/httpd.apache.org<\/li>\n<li>Apache directives: http:\/\/httpd.apache.org\/docs\/current\/mod\/directives.html<\/li>\n<li>HTTP headers: http:\/\/en.wikipedia.org\/wiki\/List_of_HTTP_header_fields<\/li>\n<li>RFC 2616 (HTTP protocol): http:\/\/www.ietf.org\/rfc\/rfc2616.txt<\/li>\n<\/ul>\n<h3 id=\"license-copying-further-use\">License \/ Copying \/ Further use<\/h3>\n<p><a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-nc-sa\/4.0\/\"><img decoding=\"async\" alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https:\/\/i.creativecommons.org\/l\/by-nc-sa\/4.0\/80x15.png\" \/><\/a><br \/>This work is licensed under a <a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-nc-sa\/4.0\/\">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License<\/a>.<\/p>\n<h5 id=\"changelog\">Changelog<\/h5>\n<ul>\n<li>2022-12-14: Change HTTP method of trace-ascii example to POST<\/li>\n<li>2018-04-13: Update title format (markdown); rewordings (Simon Studer)<\/li>\n<li>2017-02-25: Rewording part of the \u201cWhy are we doing this\u201d section, get rid of AllowOverride completely<\/li>\n<li>2016-10-09: Fixing small issues<\/li>\n<li>2016-07-15: Apache 2.4.20 -&gt; 2.4.23<\/li>\n<li>2016-03-12: Translated to English<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Configuring a minimal Apache server What are we doing? We are configuring a minimal Apache web server and will occasionally be talking to it with curl, the TRACE method and ab. Why are we doing this? A secure server is one that permits only as much as what is really needed. Ideally, you would build [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-945","page","type-page","status-publish","czr-hentry"],"_links":{"self":[{"href":"https:\/\/www.netnea.com\/cms\/wp-json\/wp\/v2\/pages\/945","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.netnea.com\/cms\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.netnea.com\/cms\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.netnea.com\/cms\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.netnea.com\/cms\/wp-json\/wp\/v2\/comments?post=945"}],"version-history":[{"count":2,"href":"https:\/\/www.netnea.com\/cms\/wp-json\/wp\/v2\/pages\/945\/revisions"}],"predecessor-version":[{"id":2055,"href":"https:\/\/www.netnea.com\/cms\/wp-json\/wp\/v2\/pages\/945\/revisions\/2055"}],"wp:attachment":[{"href":"https:\/\/www.netnea.com\/cms\/wp-json\/wp\/v2\/media?parent=945"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}