Evert Pot400 Bad Request (13.11.2018, 15:00 UTC)

400 Bad Request is the first error code. Every status that starts with a 4 indicates that the client did something wrong. If the status starts with a 5 it means that the server did something wrong.

400 Bad Request is used as a generic error code. It’s a useful default error code if there’s no specific error code that’s a better fit.

There’s often a lot of discussion about which 4xx code is the most appropriate for any different situations. This might be because there’s many, and it’s not always super clear what the distinctions between them are.

The most important thing to remember when selecting the appropriate code is: “can a generic client do something with this response?”. If the answer is no, it might not matter as much which error code is returned.

For example, when a client sees a 401 it might know to show a login window. When a client sees a 403, it might know to tell the end-user that the reason their operation failed, was because of permissions-related issues.

Those are good reasons to show an error code, but those reasons don’t always exists. For those cases it’s fine to just use the generic status code 400.

Response bodies

When returning any error, you should also return a response body with more information about the failure. If your client is a browser, this might be user-friendly HTML page. If your client is some kind of JSON-based client, it might be good idea to use the standard application/problem+json response code.


HTTP/1.1 400 Bad Request
Content-Type: application/problem+json

  "type": "https://example.org/impolite",
  "title": "Request was not polite enough",
  "detail": "HTTP requests must be made using a 'Please' HTTP header.


larry@garfieldtech.comBook review: Functional Programming in PHP (12.11.2018, 21:29 UTC)
Book review: Functional Programming in PHP

I was asked by php[architect] a while back to review "Functional Programming in PHP, 2nd Ed" by Simon Holywell. I've been sitting on this review for a while, so it's time to finally get it done.

Continue reading this review on SteemIt.

Larry 12 November 2018 - 4:29pm
Evert PotGoogle Trends for REST, GraphQL and RPC (10.11.2018, 18:52 UTC)
<script type="text/javascript" src="https://ssl.gstatic.com/trends_nrtr/1605_RC01/embed_loader.js"> <script type="text/javascript"> trends.embed.renderExploreWidget("TIMESERIES", {"comparisonItem":[{"keyword":"rest api","geo":"","time":"today 5-y"},{"keyword":"RPC","geo":"","time":"today 5-y"},{"keyword":"GraphQL","geo":"","time":"today 5-y"}],"category":5,"property":""}, {"exploreQuery":"cat=5&date=today%205-y&q=rest%20api,RPC,GraphQL","guestPath":"https://trends.google.com:443/trends/embed/"});

If you don’t see a diagram, your browser might be blocking it. See the source here.

PHP: Hypertext PreprocessorPHP 7.1.24 Released (8.11.2018, 00:00 UTC)
PHP 7.1.24 Release AnnouncementThe PHP development team announces the immediate availability of PHP 7.1.24. This is a bugfix release.All PHP 7.1 users are encouraged to upgrade to this version.For source downloads of PHP 7.1.24 please visit our downloads page, Windows source and binaries can be found on windows.php.net/download/. The list of changes is recorded in the ChangeLog.
PHP: Hypertext PreprocessorPHP 7.3.0RC5 Released (8.11.2018, 00:00 UTC)
The PHP team is glad to announce the next PHP 7.3.0 pre-release, PHP 7.3.0RC5. The rough outline of the PHP 7.3 release cycle is specified in the PHP Wiki. For source downloads of PHP 7.3.0RC5 please visit the download page. Windows sources and binaries can be found on windows.php.net/qa/. Please carefully test this version and report any issues found in the bug reporting system. THIS IS A DEVELOPMENT PREVIEW - DO NOT USE IT IN PRODUCTION! For more information on the new features and other changes, you can read the NEWS file, or the UPGRADING file for a complete list of upgrading notes. Internal changes are listed in the UPGRADING.INTERNALS file. These files can also be found in the release archive. The next release would be RC6, planned for November 22nd. The signatures for the release can be found in the manifest or on the QA site. Thank you for helping us make PHP better.
Evert PotWhich redirect do I choose? (7.11.2018, 15:00 UTC)

The 3xx status-codes are a bit of a mess. There’s a lot of confusion and mis-use, so I thought it might help to sum all of them up in a single article.

Choosing the right redirect

Are you responding to a POST request, and instead of returning a status immediately, you want to redirect the user to a confirmation page?

Use 303 See Other.

Did the resource move to a new path, or a new domain, and you want to make sure that any HTTP client repeats the exact same HTTP request on the new location?

Use 307 Temporary Redirect if the move was temporary, or 308 Permanent Redirect if the move was permanent.

Did the resource move, but you only care about GET request? (perhaps because this is a website).

Use 302 Found if the move was temporary, or 301 Moved Permanently if the move was permanent.

Do you want to send the user somewhere else, but you’re not sure where because there’s more than one option, and you’d like the user to decide:

Use 300 Multiple Choices.


Voices of the ElePHPantInterview with Jonathan Wage (6.11.2018, 17:04 UTC)

This episode is sponsored by


The post Interview with Jonathan Wage appeared first on Voices of the ElePHPant.

Evert Pot308 Permanent Redirect (6.11.2018, 15:00 UTC)

308 Permanent Redirect is similar to 301 Moved Permanently. Both indicate that the resource the user tried to access has moved to a new location. In both cases the client should update any bookmarks they had from the old to the new location. Search engines respect these statuses too.

The difference between 301 and 308 is that a client that sees a 308 redirect MUST do the exact same request on the target location. If the request was a POST and and had a body, then the client must do a POST request with a body on the new location.

In the case of 301 a client may do this. In practice, most clients don’t do this and convert the POST request to a GET request.

The 308 is relatively new, and is currently marked as experimental in RFC7238. Most modern clients support it, but you might run into some issues with older clients.


HTTP/1.1 308 Permanent Redirect
Location: https://evertpot.com/http/308-permanent-redirect
Server: Apache/2.4.29


  • RFC7238 - Status Code 308 (Permanent Redirect).
Matthew Weier O'PhinneyFixing Redis background-save issues on Docker (4.11.2018, 13:52 UTC)

I've been running redis in Docker for a number of sites, to perform things such as storing session data, hubot settings, and more.

I recently ran into a problem on one of my systems where it was reporting:

Can't save in background: fork: Out of memory

A quick google search showed this is a common error, so much so that there is an official FAQ about it. The solution is to toggle the /proc/sys/vm/overcommit_memory to 1.

The trick when using Docker is that this needs to happen on the host machine.

This still didn't solve my problem, though. So I ran a docker ps on the host machine to get an idea of what was happening. And discovered that, somehow, I had two identical redis containers running, using the exact same configuration - which meant they were doing backups to the same volume. Killing the one no longer being used by my swarm services caused everything to work once again.

mwopFixing Redis background-save issues on Docker was originally published 4 November 2018 on https://mwop.net by .
Matthew Weier O'PhinneyBuilding a usable ext-tidy for Alpine-based PHP Docker images (1.11.2018, 22:23 UTC)

I've been working on building PHP Docker images for the purposes of testing, as well as to potentially provide images containing the Swoole extension. This is generally straight-forward, as the official PHP images are well-documented.

This week, I decided to see if I could build Alpine-based images, as they can greatly reduce the final image size. And I ran into a problem.

One of the test-beds I use builds RSS and Atom feeds using zend-feed. When I tried one of these images, I started getting failures like the following:

PHP Warning:  DOMDocument::loadXML(): xmlParseEntityRef: no name in Entity, line: 167 in /var/www/vendor/zendframework/zend-feed/src/Writer/Renderer/Entry/Atom.php on line 404
PHP Fatal error:  Uncaught TypeError: Argument 1 passed to DOMDocument::importNode() must be an instance of DOMNode, null given in /var/www/vendor/zendframework/zend-feed/src/Writer/Renderer/Entry/Atom.php:371
Stack trace:
#0 /var/www/vendor/zendframework/zend-feed/src/Writer/Renderer/Entry/Atom.php(371): DOMDocument->importNode(NULL, 1)
#1 /var/www/vendor/zendframework/zend-feed/src/Writer/Renderer/Entry/Atom.php(53): Zend\Feed\Writer\Renderer\Entry\Atom->_setContent(Object(DOMDocument), Object(DOMElement))
#2 /var/www/vendor/zendframework/zend-feed/src/Writer/Renderer/Feed/Atom.php(91): Zend\Feed\Writer\Renderer\Entry\Atom->render()
#3 /var/www/vendor/zendframework/zend-feed/src/Writer/Feed.php(237): Zend\Feed\Writer\Renderer\Feed\Atom->render()
#4 /var/www/src/Blog/Console/FeedGenerator.php(209): Zend\Feed\Writer\Feed->export('Atom')

During an initial search, this appeared to be a problem due to libxml2 versions, and so I went down a rabbit hole trying to get an older libxml2 version in place, and have all of the various XML extensions compile against it. However, the error persisted.

So, I did a little more sleuthing. I fired up the container with a shell:

$ docker run --entrypoint /bin/sh -it php:7.2-cli-alpine3.8

From there, I used apk to add some editing and debugging tools so I could manually step through some of the code. In doing so, I was able to discover the exact feed item that was causing problems, and, better, get the content it was trying to use.

I realized at that point that the problem was the content — which was being massaged via the tidy extension before being passed to DOMDocument::loadXML(). For some reason, the content generated was not valid XML! (Which is really, really odd, as the whole point of tidy is to produce valid markup!)

I checked the version of ext-tidy, and what version of libtidy it was compiled against, and then checked against the php:7.2-cli image to see what it had, and discovered that while Alpine was using libtidy 5.6.0, the Debian-based image was using 5.2.0. In fact, Ubuntu 18:10 still distributes 5.2.0!

So, I then went on a quest to figure out how to get the earlier libtidy version, and compile the tidy extension against it. This is what I came up with:

# DOCKER-VERSION        1.3.2

FROM php:7.2-cli-alpine3.8

# Compile-time dependencies
RUN echo 'http://dl-cdn.alpinelinux.org/alpine/v3.6/community' >> /etc/apk/repositories
RUN apk update && \
  apk add --no-cache 'tidyhtml-dev==5.2.0-r1'

# Install the extension
RUN docker-php-ext-install -j$(nproc) tidy

Once I'd built an image using the above, I tried out my code, and the errors disappeared!

This post mainly exists because my google searches were finding nothing. Hopefully, somebody else who runs into the problem will get something useful going forward!

mwopBuilding a usable ext-tidy for Alpine-based PHP Docker images was originally published 1 November 2018 on https://mwop.net by .
LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP