:earth_asia: Functions for making sense out of URIs in PHP

Related tags

URL url php uri sabre rfc3986
Overview

sabre/uri

sabre/uri is a lightweight library that provides several functions for working with URIs, staying true to the rules of RFC3986.

Partially inspired by Node.js URL library, and created to solve real problems in PHP applications. 100% unitested and many tests are based on examples from RFC3986.

The library provides the following functions:

  1. resolve to resolve relative urls.
  2. normalize to aid in comparing urls.
  3. parse, which works like PHP's parse_url.
  4. build to do the exact opposite of parse.
  5. split to easily get the 'dirname' and 'basename' of a URL without all the problems those two functions have.

Build status

branch status minimum PHP version
master Build Status PHP 7.0
1.x Build Status PHP 5.4.7

Further reading

Questions?

Head over to the sabre/dav mailinglist, or you can also just open a ticket on GitHub.

Made at fruux

This library is being developed by fruux. Drop us a line for commercial services or enterprise support.

Comments
  • parse() does not handle custom protocol with root slash, like whatever:///whatever

    parse() does not handle custom protocol with root slash, like whatever:///whatever

    As this package is called sabre/uri, and not sabre/url, I expected it to handle any valid URI. For example, it should handle any URI scheme. However, that is not the case, because it uses parse_url internally. The docs clearly say that

    This function is intended specifically for the purpose of parsing URLs and not URIs. However, to comply with PHP's backwards compatibility requirements it makes an exception for the file:// scheme where triple slashes (file:///...) are allowed. For any other scheme this is invalid.

    http:// and file:// work, any other URI results in an Errror: Unsupported operand types.

    Examples:

    Uri\parse('ftp:///whatever')
    Uri\parse('ssh://[email protected]/fruux/sabre-uri.git')
    

    This really limits the usefulness of this function.

    bug 
    opened by felixfbecker 14
  • Colon ':' in urls causing problems

    Colon ':' in urls causing problems

    Relating to this issue: https://github.com/owncloud/core/issues/23740

    Tested on php 7.0.4 on Ubuntu 16.04.

    The parse function in lib/functions.php has trouble with colon characters in the wrong place in the uri. The parse function in turn uses php's parse_url function which is what is failing under certain (odd) circumstances.

    If there is a colon character as the second to last character in a uri phps parse_url function fails to parse the uri. When phps parse_url function fails and returns false, sabres parse function also fails. It's also worth noting that phps parse_url works if you move the colon anywhere else in the string.

    Here's how this can be reproduced:

    <?php print "Works:\n"; var_dump(parse_url('/webdav/test3')); print "\nFails:\n"; var_dump(parse_url('/webdav/test:3')); ?>

    I'm not sure how or where this is most appropriate to fix.

    Thanks

    bug 
    opened by sii 14
  • Document InvalidUriException

    Document InvalidUriException

    _parse_fallback(), together with functions that directly or indirectly call it, are missing @throws in their respective docblocks.

    This is annoying for static analysis, for example PHPStorm tells me:

    image

    This PR adds @throws where appropriate.

    opened by BenMorel 9
  • Windows file prefix

    Windows file prefix

    I know that there's been multiple discussions in multiple places about this. But please bear with me.

    The following refers to a valid path and file on my Windows 10 machine:

    <?php
    include './vendor/autoload.php';
    use Sabre\Uri;
    
    $basePath = 'file:///C:/Repos/my-path/tests/';
    $newPath = 'my-file.json';
    
    var_dump(Uri\resolve($basePath, $newPath));
    //Outputs "file://C:/Repos/my-path/tests/my-file.json"
    

    Which fails because it replaced file:/// with file:// and the C: is therefore treated as host:port

    Could you please either let me know what I'm doing wrong, or if it is a bug, let me know and I'll organise a PR for you.

    Thank you.

    bug 
    opened by mlambley 7
  • Specify detailed return type of parse()

    Specify detailed return type of parse()

    If I increase phpstan level to 9, then it detects that function parse(string $uri): array can return array<string, int|string|null> and that is correct.

    Key "port" is an int value. Other keys have a string value. "Unused" keys have value null.

    If I actually document:

     * @return array<string, int|string|null>
    

    Then phpstan complains about:

    ------ ------------------------------------------------------------------------------------------------- 
      Line   lib/functions.php                                                                                
     ------ ------------------------------------------------------------------------------------------------- 
      60     Parameter #1 $string of function substr expects string, int|string|null given.                   
      68     Parameter #2 $str of function explode expects string, int<min, -1>|int<1, max>|string given.     
      117    Parameter #1 $str of function ltrim expects string, int<min, -1>|int<1, max>|string given.       
      138    Parameter #1 $str of function strtolower expects string, int<min, -1>|int<1, max>|string given.  
      161    Parameter #1 $str of function strtolower expects string, int<min, -1>|int<1, max>|string given.  
     ------ ------------------------------------------------------------------------------------------------- 
    

    because it has not been told the detail that: Key "port" can have value int|null All other keys have value string|null

    If there is some way to express this in PHPdoc, then that would be good - because the line numbers above are processing keys that do not have int value.

    For now, I set the type of the keys to mixed - at least that recognizes that the values are definitely not all string.

    opened by phil-davis 6
  • Add empty host and trailing slash to windows file paths

    Add empty host and trailing slash to windows file paths

    This is a rebase of PR #25 with conflicts resolved...

    In the 2nd commit, I have added some comments and simplified the windows_path regex in a similar way to what @peterpostmann has suggested in comment https://github.com/sabre-io/uri/pull/25#discussion_r946370109

    opened by phil-davis 6
  • windows file:// uri resolving

    windows file:// uri resolving

    Hello!

    I'm using league/json-reference library for json validation, and this library uses sabre/uri for resolving external references in json-schema.

    Everything works fine on Linux machines, but not on Windows. For example if function Sabre\Uri\resolve being called with parameters

    $basePath = 'file://D:/development/projects/markirovka/storage/app/jsonSchemas/undefined_order.json';
    $newPath = './types/turnover_type.json';
    

    result will be

    file://D/development/projects/markirovka/storage/app/jsonSchemas/types/turnover_type.json
    

    The comma after disk partition letter will be missed, and it couse an error.

    I've being debugging a bit, and I think it can be fixed with minor changes in lib/functions. Function for Windows detection:

    /**
     * This function returns true if aplication run in Windows environment
     * @return bool
     */
    function isWindows() {
        return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
    }
    

    And changes in build function:

    function build(array $parts) {
    
        $uri = '';
    
        $authority = '';
        if (!empty($parts['host'])) {
            $authority = $parts['host'];
            if (!empty($parts['user'])) {
                $authority = $parts['user'] . '@' . $authority;
            }
            if (!empty($parts['port'])) {
                $authority = $authority . ':' . $parts['port'];
            }
        }
    // ============= add this ===============
        /**
         * on Windows systems for local URIs $parts['host'] will be a partition letter,
         * and we must add colon after it
         */
        if (isWindows() && !empty($parts['scheme']) && $parts['scheme'] == 'file') {
            $authority .= ':';
        }
    // ==================================
    
        if (!empty($parts['scheme'])) {
            // If there's a scheme, there's also a host.
            $uri = $parts['scheme'] . ':';
    
        }
        if ($authority || (!empty($parts['scheme']) && $parts['scheme'] === 'file')) {
            // No scheme, but there is a host.
            $uri .= '//' . $authority;
    
        }
    
        if (!empty($parts['path'])) {
            $uri .= $parts['path'];
        }
        if (!empty($parts['query'])) {
            $uri .= '?' . $parts['query'];
        }
        if (!empty($parts['fragment'])) {
            $uri .= '#' . $parts['fragment'];
        }
    
        return $uri;
    }
    

    What do you think about this suggestion?

    And excuse my english, it's not my native language.

    question 
    opened by nobbynobbs 6
  • Windows host handling

    Windows host handling

    Hi,

    I think a found a bug on windows. For the uri 'file:///C:/path/file_a.ext' parse returns

    array (size=2)
      'scheme' => string 'file' (length=4)
      'path' => string 'C:/path/file_a.ext' (length=18)
    

    This causes resolve('file:///C:/path/file_a.ext', 'file_b.ext') to generate wrong URIs: file://C:/path/file_b.ext (one slash is missing, because the empty host is missing).

    parse_url produces the same result, which is correct with reagards to http://php.net/manual/en/wrappers.file.php, but it cannot be used to reconstruct file uris directly.

    The behavior of _parse_fallback is correct and has this output:

    array (size=3)
      'scheme' => string 'file' (length=4)
      'path' => string '/C:/path/file_a.ext' (length=19)
      'host' => string '' (length=0)
    

    parse should also produce this output.

    Note: I had to remove the white spaces before and after the regex because I couldn't get it tested otherwise (using PHP 7.1)

    opened by peterpostmann 6
  • Add empty host and leading slash to Windows file paths

    Add empty host and leading slash to Windows file paths

    1. add an explicit unit test for issue #31
    2. Adjust README to mention Windows-style paths
    3. Add empty host and leading slash to Windows file paths (this is a remake of PR #71
    4. changelog and version bump to 3.0.0
    opened by phil-davis 5
  • Field

    Field "pass" not handled correctly

    While using sabre/uri in a work project, I noticed an inconsistency. It looks almost like the author forgot about the "pass" field:

    1. parse() does not include "pass" with null value if no password is found in the URI,
    2. build() does not include "pass" in the string URI even when it's passed in the input data.
    opened by vojtagrec 5
  • Workaround for parsing colons in partial URLs

    Workaround for parsing colons in partial URLs

    Whenever a URL contains no host part, the presence of a colon will make PHP's parse_url fail. To workaround this bug, we need to encode the colon in this situation.

    However we do not encode colons for full URLs.

    Fixes https://github.com/fruux/sabre-uri/issues/9

    @evert would you accept a backport for this to the sabre-uri 1.0 series ? (not sure how to proceed, no stable branches ?)

    Please review

    opened by PVince81 4
  • Parsing Windows file:/// URIs is now broken

    Parsing Windows file:/// URIs is now broken

    I did a minor upgrade on https://github.com/zobo/php-language-server and and after spending hours on debugging why a whole lot of things stopped working realized that Release 2.2.3 with #71 changed how Windows file URIs are parsed.

    Now instead of getting path: C:/dir/... we get path: /C:/dir/....

    I have looked into a few different issues here to figure out why this would be OK, but I'm sorry, this is a breaking change and should have been released under a new major version.

    opened by zobo 7
  • Urlencode in parse?

    Urlencode in parse?

    Something not mentioned in the official documentation:

    https://sabre.io/uri/usage/

    but only in the source code:

    https://github.com/sabre-io/uri/blob/master/lib/functions.php

    is this piece:

    // Normally a URI must be ASCII, however. However, often it's not and
    // parse_url might corrupt these strings.
    //
    // For that reason we take any non-ascii characters from the uri and
    // uriencode them first.
    $uri = preg_replace_callback(
        '/[^[:ascii:]]/u',
        function ($matches) {
            return rawurlencode($matches[0]);
        },
        $uri
    );
    

    Urlencoding is NOT appropriate for domain name / FQDN!

    For example, these IRIs:

    • https://пример.рф/
    • https://приклад.укр/
    • https://παράδειγμα.ελ/

    should NOT be parsed to:

    array (size=7)
      'scheme' => string 'https' (length=5)
      'host' => string '%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80.%D1%80%D1%84' (length=49)
      'path' => string '/' (length=1)
      ...
    
    array (size=7)
      'scheme' => string 'https' (length=5)
      'host' => string '%D0%BF%D1%80%D0%B8%D0%BA%D0%BB%D0%B0%D0%B4.%D1%83%D0%BA%D1%80' (length=61)
      'path' => string '/' (length=1)
      ...
    
    array (size=7)
      'scheme' => string 'https' (length=5)
      'host' => string '%CF%80%CE%B1%CF%81%CE%AC%CE%B4%CE%B5%CE%B9%CE%B3%CE%BC%CE%B1.%CE%B5%CE%BB' (length=73)
      'path' => string '/' (length=1)
      ...
    

    Instead they should be parsed to:

    array (size=7)
      'scheme' => string 'https' (length=5)
      'host' => string 'пример.рф' (length=17)
      'path' => string '/' (length=1)
      ...
    
    array (size=7)
      'scheme' => string 'https' (length=5)
      'host' => string 'приклад.укр' (length=21)
      'path' => string '/' (length=1)
      ...
    
    array (size=7)
      'scheme' => string 'https' (length=5)
      'host' => string 'παράδειγμα.ελ' (length=25)
      'path' => string '/' (length=1)
      ...
    
    opened by DanAlexson90 1
  • Unknown modifier error on the regex for uris that have an authority part

    Unknown modifier error on the regex for uris that have an authority part

    Sorry to hassle you again folks, but I'm running the tests on the project and am coming up against an issue with functions.php line 360.

    Numerous tests are failing with the same issue, but I'm focusing on the "http://example.org:8080/" test.

    I've pasted the relevant code into http://sandbox.onlinephpfunctions.com/ so that I can test it against different PHP versions. The code is:

    <?php
    $uri = '//example.org:8080/';
    $regex = '
              %^
                //
                (?: (?<user> [^:@]+) (: (?<pass> [^@]+)) @)?
                (?<host> ( [^:/]* | \[ [^\]]+ \] ))
                (?: : (?<port> [0-9]+))?
                (?<path> / .*)?
              $%x
            ';
    var_dump(preg_match($regex, $uri, $matches));
    var_dump($matches);
    

    The error I'm getting is:

    <b>Warning</b>:  preg_match(): Unknown modifier '
    ' in <b>[...][...]</b> on line <b>12</b><br />
    bool(false)
    NULL
    

    Any advice would be appreciated. Thank you.

    opened by mlambley 1
Releases(3.0.0)
  • 3.0.0(Sep 26, 2022)

    3.0.0 (2022-09-26)

    • #82: Add empty host and leading slash to Windows file paths (@peterpostmann @phil-davis)

    This changes the behavior of parsing of some Windows file paths. See the discussions in PR #82 #71 #25 and issue #31 #81

    Source code(tar.gz)
    Source code(zip)
  • 2.3.2(Sep 19, 2022)

    2.3.2 (2022-09-19)

    • #83: Revert windows file paths change (was PR 71). See issue 81 (@phil-davis)

    See the discussion in issue #81 and PR #83 and links from there. This patch release reverts to the previous behavior for Windows file paths like file:///C:/path/file.ext

    The newer behavior will be released in a major version release, so that consumers can adjust to the change, if needed, in a more controlled manner.

    Source code(tar.gz)
    Source code(zip)
  • 2.2.4(Sep 19, 2022)

    2.2.4 (2022-09-19)

    • #83: Revert windows file paths change (was PR 71). See issue 81 (@phil-davis)

    See the discussion in issue #81 and PR #83 and links from there. This patch release reverts to the previous behavior for Windows file paths like file:///C:/path/file.ext

    The Windows file paths change was released in 2.2.3. So this 2.2.4 release allows anyone on 2.2.3 to bump just the patch version to 2.2.4 to get back the old behavior. This will be relevant to consumers who are still using PHP 7.1 7.2 or 7.3, and are thus on 2.2.. The 2.2. series is the last release series for those PHP versions.

    The newer behavior will be released in a major version release, so that consumers can adjust to the change, if needed, in a more controlled manner. That release will also require a minimum of PHP 7.4

    Source code(tar.gz)
    Source code(zip)
  • 2.3.1(Aug 30, 2022)

    2.3.1 (2022-08-30)

    • #77: Add PHP 8.2 to CI - confirms that the code is working with PHP 8.2 (@phil-davis)
    • #78: Raise phpstan to level 8 (@phil-davis)
    • #79: Specify detailed return type of parse() (@phil-davis)
    Source code(tar.gz)
    Source code(zip)
  • 2.3.0(Aug 17, 2022)

  • 2.2.3(Aug 17, 2022)

    2.2.3 (2022-08-17)

    • #71: Add empty host and trailing slash to windows file paths (@peterpostmann @phil-davis)
    • #70: Update .gitattributes (@cedric-anne)
    Source code(tar.gz)
    Source code(zip)
  • 2.2.2(Nov 4, 2021)

  • 2.2.1(Oct 3, 2020)

  • 2.2.0(Jan 31, 2020)

    2.2.0 (2020-01-31)

    • #45 Added Support for PHP 7.4 (@phil-davis, @staabm)
    • #47: Dropped Support for PHP 7.0 (@phil-davis)
    • #49: Updated the testsuite for phpunit8 (@phil-davis)
    • #46: Added phpstan coverage (@phil-davis)
    Source code(tar.gz)
    Source code(zip)
  • 2.1.3(Sep 10, 2019)

  • 2.1.2(Jun 25, 2019)

  • 2.1.1(Jun 25, 2019)

  • 1.2.1(Jun 25, 2019)

  • 2.1.0(Dec 7, 2016)

    • Now throwing InvalidUriException if a uri passed to the parse function is invalid or could not be parsed.
    • #11: Fix support for URIs that start with a triple slash. PHP's parse_uri() doesn't support them, so we now have a pure-php fallback in case it fails.
    • #9: Fix support for relative URI's that have a non-uri encoded colon : in them.
    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Dec 7, 2016)

    • Now throwing InvalidUriException if a uri passed to the parse function is invalid or could not be parsed.
    • #11: Fix support for URIs that start with a triple slash. PHP's parse_uri() doesn't support them, so we now have a pure-php fallback in case it fails.
    • #9: Fix support for relative URI's that have a non-uri encoded colon : in them.
    Source code(tar.gz)
    Source code(zip)
  • 2.0.1(Dec 7, 2016)

  • 1.1.1(Dec 7, 2016)

  • 2.0.0(Oct 7, 2016)

  • 1.1.0(Mar 12, 2016)

    • #6: PHP's parse_url() corrupts strings if they contain certain non ascii-characters such as Chinese or Hebrew. sabre/uri's parse() function now percent-encodes these characters beforehand.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Mar 12, 2016)

    • #4: Using php-cs-fixer to automatically enforce conding standards.
    • #5: Resolving to and building mailto: urls were not correctly handled.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Mar 12, 2016)

    • Added a normalize function.
    • Added a buildUri function.
    • Fixed a bug in the resolve when only a new fragment is specified.

    San José, CalConnect XXXII release!

    Source code(tar.gz)
    Source code(zip)
  • 0.0.1(Nov 18, 2014)

Purl is a simple Object Oriented URL manipulation library for PHP 7.2+

Purl Purl is a simple Object Oriented URL manipulation library for PHP 7.2+ Installation The suggested installation method is via composer: composer r

Jonathan H. Wage 908 Dec 21, 2022
A simple URL shortener for PHP

Shorty Shorty is a simple URL shortener for PHP. Installation 1. Download and extract the files to your web directory. 2. Use the included database.sq

Mike Cao 210 Dec 19, 2022
shortUrl - PHP - Witout-API ☔

shortUrl - PHP - Witout-API ☔

ARAR AL-DOSRI 3 Jun 27, 2022
A PHP-based self-hosted URL shortener that can be used to serve shortened URLs under your own custom domain.

A PHP-based self-hosted URL shortener that can be used to serve shortened URLs under your own custom domain. Table of Contents Full documentation Dock

null 1.7k Dec 29, 2022
URL shortener web application based on the Laravel PHP Framework.

UrlHub Warning: UrlHub is still in development, constantly being optimized and isn't still stable enough to be used in production environments. Whatev

Kei 349 Jan 4, 2023
The modern, privacy-aware URL Shortener built in PHP.

About UrlHum UrlHum is a modern, privacy-aware and fast URL Shortener built with PHP and the Laravel Framework. At the moment UrlHum is heavily under

UrlHum 622 Jan 7, 2023
URL shortener web application based on the Laravel PHP Framework.

UrlHub Warning: UrlHub is still in development, constantly being optimized and isn't still stable enough to be used in production environments. Whatev

Kei 348 Dec 23, 2022
A simple PHP library to parse and manipulate URLs

Url is a simple library to ease creating and managing Urls in PHP.

The League of Extraordinary Packages 351 Dec 30, 2022
YCOM Impersonate. Login as selected YCOM user 🧙‍♂️in frontend.

YCOM Impersonate Login as selected YCOM user in frontend. Features: Backend users with admin rights or YCOM[] rights, can be automatically logged in v

Friends Of REDAXO 17 Sep 12, 2022
Making multiple identical function calls has the same effect as making a single function call.

Making multiple identical function calls has the same effect as making a single function call.

李铭昕 4 Oct 16, 2021
Here is the top 100 PHP functions: it is the list of the most often used PHP native functions

Here is the top 100 PHP functions: it is the list of the most often used PHP native functions. If you are a PHP developer, you must know the Top 100 PHP Functions deeply.

Max Base 16 Dec 11, 2022
Simple MySQL library for PHP 5.4+ includes Query Builder, PDO Native functions, Helper functions for quick use.

Simple MySQL library for PHP 5.4+ includes Query Builder, PDO Native functions, Helper functions for quick use.

Kodols 9 Dec 22, 2022
Magento-Functions - A Resource of Magento Functions

Magento-Functions A Resource of Magento Functions Table of Contents Category Product User Cart Checkout General Account [Working w/ URL's] (#urls) Cat

Bryan Littlefield 28 Apr 19, 2021
Symplify - Making Everyday PHP Development Simple

Symplify - Making Everyday PHP Development Simple In this monorepo you'll find PHP packages that help you with: your first coding standard maintenance

null 628 Dec 19, 2022
YesWiki is a wiki system written in PHP, including extensions making collaboration more simple (databases, maps, easy editing, bootstrap themes,...).

YesWiki YesWiki is a Free Software under the AGPL licence, made for creating and managing your website, in a collaborative way. YesWiki allows any web

YesWiki 84 Dec 26, 2022
This is an attempt at making my own personal PHP framework purely for learning purposes.

PHP-MVC-FRAMEWORK This is an attempt at making my own personal PHP framework purely for learning purposes. Installation Download the archive or clone

Alvin Kigen 3 Feb 5, 2022
Making phone calls with PHP and Twilio Voice Service.

TwilioVoice-PHP This is an example implementation of Twilio's phone call API. You can clone this code to your project: git clone https://github.com/P

Philipe  Lima 2 Nov 15, 2022
Helpers for making PHP enums more lovable.

Enums A collection of enum helpers for PHP. InvokableCases Names Values Options From Metadata You can read more about the idea on Twitter. I originall

ARCHTECH 212 Dec 22, 2022
Making Eloquent models translatable

A trait to make Eloquent models translatable This package contains a trait to make Eloquent models translatable. Translations are stored as json. Ther

Spatie 1.9k Jan 7, 2023
Laravel API starter Kit will provide you with the tools for making API's that everyone will love

Laravel API Starter Kit Laravel API starter Kit will provide you with the tools for making API's that everyone will love, API Authentication is alread

Jose Luis Fonseca 400 Dec 29, 2022