Coder Social home page Coder Social logo

url's Introduction

Parse, build and manipulate URLs

Latest Version on Packagist Tests Total Downloads

A simple package to deal with URLs in your applications.

Installation

You can install the package via composer:

composer require spatie/url

Usage

Parse and transform a URL

Retrieve any part of the URL:

use Spatie\Url\Url;

$url = Url::fromString('https://spatie.be/opensource');

echo $url->getScheme(); // 'https'
echo $url->getHost(); // 'spatie.be'
echo $url->getPath(); // '/opensource'

Transform any part of the URL:

Note the Url class is immutable.

$url = Url::fromString('https://spatie.be/opensource');

echo $url->withHost('github.com')->withPath('spatie');
// 'https://github.com/spatie'

Scheme

Transform the URL scheme.

$url = Url::fromString('http://spatie.be/opensource');

echo $url->withScheme('https'); // 'https://spatie.be/opensource'

Use a list of allowed schemes.

Note each scheme in the list will be sanitized

$url = Url::fromString('https://spatie.be/opensource');

echo $url->withAllowedSchemes(['wss'])->withScheme('wss'); // 'wss://spatie.be/opensource'

or pass the list directly to fromString as the URL's scheme will be sanitized and validated immediately:

$url = Url::fromString('https://spatie.be/opensource', [...SchemeValidator::VALID_SCHEMES, 'wss']);

echo $url->withScheme('wss'); // 'wss://spatie.be/opensource'

Query parameters

Retrieve and transform query parameters:

$url = Url::fromString('https://spatie.be/opensource?utm_source=github&utm_campaign=packages');

echo $url->getQuery(); // 'utm_source=github&utm_campaign=packages'

echo $url->getQueryParameter('utm_source'); // 'github'
echo $url->getQueryParameter('utm_medium'); // null
echo $url->getQueryParameter('utm_medium', 'social'); // 'social'
echo $url->getQueryParameter('utm_medium', function() {
    //some logic
    return 'email';
}); // 'email'

echo $url->withoutQueryParameter('utm_campaign'); // 'https://spatie.be/opensource?utm_source=github'
echo $url->withQueryParameters(['utm_campaign' => 'packages']); // 'https://spatie.be/opensource?utm_source=github&utm_campaign=packages'

Path segments

Retrieve path segments:

$url = Url::fromString('https://spatie.be/opensource/laravel');

echo $url->getSegment(1); // 'opensource'
echo $url->getSegment(2); // 'laravel'

PSR-7 UriInterface

Implements PSR-7's UriInterface interface:

class Url implements UriInterface { /* ... */ }

The league/uri is a more powerful package than this one. The main reason this package exists, is because the alternatives requires non-standard php extensions. If you're dealing with special character encodings or need bulletproof validation, you're definitely better off using league/uri.

Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects on our website.

Testing

composer test

Support us

We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on our contact page. We publish all received postcards on our virtual postcard wall.

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Postcardware

You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.

Our address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium.

We publish all received postcards on our company website.

Credits

License

The MIT License (MIT). Please see License File for more information.

url's People

Contributors

adrianmrn avatar akoepcke avatar angeljqv avatar aungmyatmoe11 avatar bmitch avatar bryanlopezinc avatar bvtterfly avatar carusogabriel avatar chapeupreto avatar driesvints avatar fgilio avatar freekmurze avatar glenncoppens avatar kschatzle avatar maspeng avatar mattiasgeniar avatar matusboa avatar misantron avatar mkopinsky avatar mrk-j avatar noahfrederick avatar patinthehat avatar peter279k avatar samuelnitsche avatar sebastiandedeyne avatar srmklive avatar tjoosten avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

url's Issues

Leading slash in path

Hello,

I started using this library in a Laravel project.

The request's path method in Laravel does not include the leading slash in the returned value (https://laravel.com/docs/7.x/requests#request-path-and-method), the path method in this library include it.

I understand that this library is not directly connected with Laravel, but is it conceivable to standardize it? Or create a new method or option on the existing method?

Thanks!

Trailing Slash is removed

This package seems to remove the trailing slash aggressively with no way of avoiding of it?

I discovered this while using Guzzle so i'll give simple example and a real world example of how I encountered it.

$link = 'https://www.domain.com/wp-json/wp/v2/';
$url = Url::fromString($link);

// returns https://www.domain.com/wp-json/wp/v2 
// note the missing trailing slash
echo $url;

This caused a problem with guzzle like so:

// This gives an error URI must be a string or UriInterface
$guzzle = new HttpClient([
        'base_uri'  =>  $url
    ]);

// This strips the v2 because guzzle looks for a trailing slash and strips if it doesn't exist
$guzzle = new HttpClient([
        'base_uri'  =>  (string)$url
    ]);

// The url attempted is https://www.domain.com/wp-json/wp/posts
// note the missing "v2"
$guzzle->get('posts');

I guess you could say it's an issue with guzzle aggressively removing the last segment. But much of a muchness.

Unfortunately I don't know what to suggest in terms of a solution, at the very least it should be documented that the trailing slash is removed.

Easy way to remove query string?

Hi. This doesn't work:

$url = Url::fromString('https://somehost.com/some/path?param=1');

$clean_url = $url->withHost($url->getHost())->withPath($url->getPath());

var_dump($clean_url); // returns the $url object
var_dump($clean_url->__toString()); // returns 'https://somehost.com/some/path?param=1'

Thanks.

Full example in the introduction to spatie/url

This may be obvious to most, but I think the introduction would benefit from a full example on how to use this package, example:

<?php
require 'vendor/autoload.php';

use Spatie\Url\Url;

$url = Url::fromString('https://spatie.be/opensource');

echo $url->getScheme(); // 'https'
echo $url->getHost(); // 'spatie.be'
echo $url->getPath(); // '/opensource'

Happy Coding!

Default constructor result is unexpected

I was trying to add this library to my URI test suite and I stumble into this rather odd bug:

var_dump(
    (string) (new Url('http://example.com')), //display the empty string ???
    (string) Url::fromString('http://example.com') //display 'http://example.com'
);

Maybe you should protect the constructor because this is unexpected at best.

PS: the test suite reveals more problem too.

Spatie menu fails of Url::fromString method fails

Spatie menu has a method ActiveUrlChecker::check (https://github.com/spatie/menu/blob/master/src/ActiveUrlChecker.php#L10) that calls Url::fromString.

Because url path can be invalid (our case ///remote/fgt_lang?lang=/../../../..//////////dev/) it will throw an exception:

  1. parse_url('///remote/fgt_lang?lang=/../../../..//////////dev/') will return false
  2. array_merge(false) finally throw an exception https://github.com/spatie/url/blob/master/src/Url.php#L43

Why it needed to do array_merge with only 1 argument?
What to do if parse_url failed?

Url 'javascript:void();' results in fatal error

This code results in a fatal error:

<?php
require '../vendor/autoload.php';

use Spatie\Url\Url;
echo Url::fromString('javascript:void();');

Fatal error message:

Fatal error: Uncaught Spatie\Url\Exceptions\InvalidArgument: The scheme `javascript` isn't valid.
It should be either `http` or `https`.

Ability to configure `VALID_SCHEMES` or disable scheme validation

Really enjoy using this package and been using it for a number of projects.

Ran into a situation where some of the URLs I need to work with have a scheme of applewebdata.

This fails when I attempt to make a URL with this scheme since the only schemes allowed are:

    const VALID_SCHEMES = ['http', 'https', 'mailto'];

However, there are many more valid schemes than those 3:

https://tools.ietf.org/html/rfc3986#section-3.1

I'd like to make a PR to solve this situation but wanted to run this by you guys to discuss what the best solution would be before I do any coding. Some ideas are:

  • A: Removing the scheme validation altogether.
  • B: Or maybe make it something that can be turned off.
  • C: Adjusting the scheme validation to use the pattern describes in that RFC.

Thanks very much.

Add ability to get unencoded string

I recently ran into a strange problem with the Google OAuth and this package.

For some unknown reason having + replaced with %2B in a redirect to a Google OAuth URL results in an error where the scopes query parameter is not properly picked up.

So this will work:

https://accounts.google.com/o/oauth2/auth?client_id=xxx.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fdomain.net%2Fauth%2Fsocial%2Freturn%2Fgoogle&scope=openid+profile+email&response_type=code&state=xieUxnLmQv9YzBdv9dd2d1GPxvlNFWzghluO8b1G

but this does not

https://accounts.google.com/o/oauth2/auth?client_id=xxx.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fdomain.net%2Fauth%2Fsocial%2Freturn%2Fgoogle&scope=openid%2Bprofile%2Bemail&response_type=code&state=xieUxnLmQv9YzBdv9dd2d1GPxvlNFWzghluO8b1G

Note the only change is from &scope=openid+profile+email to &scope=openid%2Bprofile%2Bemail

Undoubtedly this an issue Google should fix rather than Spatie. However it does seem it would be preferable to have the option to get an unencoded string both for edge cases like this and it would probably be preferable to display the unencoded version when displaying a URL to a user on a page.

I would like to propose the following changes and am posting it as an issue first incase it needs further discussion but will happily do a pull request.

QueryParameterBag.php
From

    public function __toString()
    {
        $keyValuePairs = Arr::map($this->parameters, function ($value, $key) {
            return "{$key}=".rawurlencode($value);
        });

        return implode('&', $keyValuePairs);
    }
    public function __toString()
    {
        return $this->getString(true);
    }

    public function getString(bool $encoded = true)
    {
        $keyValuePairs = Arr::map($this->parameters, function ($value, $key) use ($encoded) {
            return "{$key}=".($encoded ? rawurlencode($value) : $value);
        });

        return implode('&', $keyValuePairs);
    }

And in Url.php

    public function __toString()
    {
        return $this->getString(true);
    }
    
    public function getString(bool $encoded = true)
    {
    {
        $url = '';

        if ($this->getScheme() !== '' && $this->getScheme() != 'mailto') {
            $url .= $this->getScheme().'://';
        }

        if ($this->getScheme() === 'mailto' && $this->getPath() !== '') {
            $url .= $this->getScheme().':';
        }

        if ($this->getScheme() === '' && $this->getAuthority() !== '') {
            $url .= '//';
        }

        if ($this->getAuthority() !== '') {
            $url .= $this->getAuthority();
        }

        if ($this->getPath() !== '/') {
            $url .= $this->getPath();
        }

        if ($this->getQuery() !== '') {
            $url .= '?'.$this->query->getString($encoded);
        }

        if ($this->getFragment() !== '') {
            $url .= '#'.$this->getFragment();
        }

        return $url;
    }

For the sake of other searchers this is the error message that lead me to this:

Authorization Error
Error 400: invalid_scope
Some requested scopes were invalid. {invalid=[openid+profile+email]}

Duplicate question mark for query params

Hi there. I recently used your library and I found that there is a problem with question mark(?) at the end of the url.

If we use a base url that already contains query parameters like : https://example.com/?param=test and add parameters using withQueryParameter('key','value') function, then it appends a new question mark that makes url not valid. in this example it will looks like:
https://example.com/?param=test?key=value

But it have to be:
https://example.com/?param=test&key=value
cause only the first ? is significant to web browsers.

Solution: You only have to change 3 lines in __toString() method:

        if ($this->getQuery() !== '') {
            if (\Str::contains($url, '?'))
                $url .= '&';
            else
                $url .= '?';

            $url .= $this->getQuery();
        }

I already extended your Url class in MyUrl class to fix the bug for now.
Please fix this or let me know if your not going to improve the library. Thanks in advance.

Android app link

Hello,
I’m using your package to manipulate and validate urls coming from a tracking script.
And I have started getting an erros because some of the url where coming from android apps with ‘android-app://com.google.android.gm/’ referrer link.

Error: Spatie\Url\Exceptions\InvalidArgument: The scheme android-app isn't valid. It should be either http, https, mailto or tel.

Ofcorse I can write condition but also I think it should be supported in this package.
What do you think?

Does not work with query parameters without values

When we trying to parse http://test.com/test?a=1&b or http://test.com/test?a=1&b&c=1 it returns error [2017-03-09 12:07:21] local.ERROR: ErrorException: Undefined offset: 1 in vendor/spatie/url/src/Helpers/Arr.php:19

Ability to get first and last segment?

Really enjoying using this package.

Was wondering if you guys were open to the ability of retrieving the first and last segment of the URL?

Something like:

    /** @test */
    public function it_can_return_the_last_path_segment()
    {
        $url = Url::create()->withPath('opensource/php');
        $this->assertEquals('php', $url->getLastSegment());
    }

    /** @test */
    public function it_can_return_the_first_path_segment()
    {
        $url = Url::create()->withPath('opensource/php');
        $this->assertEquals('opensource', $url->getFirstSegment());
    }

If so I wouldn't mind submitting a PR for it.

Bug: method withQueryParameter cleans all previous parameters

PHP: 7.4.13

Imagine this example:

$a = Url::fromString("https://spatie.be");
$a->withQueryParameter('you', 1);
$a->withQueryParameter('are', 2);
$a->withQueryParameter('awesome', 3);

echo $a->__toString();// https://spatie.be

Expected result:
https://spatie.be?you=1&are=2&awesome=3

Actual result:
https://spatie.be

How to fix

Remove __clone method.

The problem is in the _clone method, which probably had the purpose to fix this problem but now causes it. https://github.com/spatie/url/blob/master/src/Url.php#L345

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.