Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

urlparse function to get url parts #23893

Open
matti opened this issue Jan 19, 2020 · 13 comments · May be fixed by #32328
Open

urlparse function to get url parts #23893

matti opened this issue Jan 19, 2020 · 13 comments · May be fixed by #32328

Comments

@matti
Copy link

matti commented Jan 19, 2020

a workaround:

https://registry.terraform.io/modules/matti/urlparse/external/0.2.0

@apparentlymart
Copy link
Member

Thanks for sharing this, @matti!

Another option with Terraform as it exists today is to use the regular expression given in RFC 3986 Appendix A:

> regex("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?", "http://user:pass@www.example.com:8080/path?query1=1&query2=2#frag")
[
  "http:",
  "http",
  "//user:pass@www.example.com:8080",
  "user:pass@www.example.com:8080",
  "/path",
  "?query1=1&query2=2",
  "query1=1&query2=2",
  "#frag",
  "frag",
]

Or, a variant of it using named capture groups for easier consumption of the result:

> regex("(?:(?P<scheme>[^:/?#]+):)?(?://(?P<authority>[^/?#]*))?(?P<path>[^?#]*)(?:\\?(?P<query>[^#]*))?(?:#(?P<fragment>.*))?", "http://user:pass@www.example.com:8080/path?query1=1&query2=2#frag")
{
  "authority" = "user:pass@www.example.com:8080"
  "fragment" = "frag"
  "path" = "/path"
  "query" = "query1=1&query2=2"
  "scheme" = "http"
}

This particular regex pattern doesn't try to decompose the "authority" portion because it's a generic URL match rather than a scheme-specific match. Perhaps that part could be parsed in a subsequent call where needed, as a way to get this done in current Terraform releases.

@matti
Copy link
Author

matti commented Jan 30, 2020

the regexp you provided does not provide the same parts what my module does - I tried to write regexp like that but it is super hard.

@ljalbinson
Copy link

I posted on this subject elsewhere and was re-directed by Martin (thank you Martin):

For the hostname only I did the following using the go url.Parse and net.SplitHostPart functions:

+var URLToHostNameFunc = function.New(&function.Spec{

  •   Params: []function.Parameter{
    
  •           {
    
  •                   Name: "str",
    
  •                   Type: cty.String,
    
  •           },
    
  •   },
    
  •   Type: function.StaticReturnType(cty.String),
    
  •   Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
    
  •           u, _ := url.Parse(args[0].AsString())
    
  •           host, _, _ := net.SplitHostPort(u.Host)
    
  •           return cty.StringVal(host), nil
    
  •   },
    

+})
+

I don't think it would be much of a stretch to cover most of the other cases.

Kind regards, Lawrence

@ljalbinson
Copy link

Sorry for the broken code insert.

@mkielar
Copy link

mkielar commented Oct 21, 2021

How disappointing this simple feature is not getting enough attention.
Our use case is this:
We deploy AppMesh Virtual Services for all of our external integrations. So let's say we have following setup:

  1. https://example.com:8112
  2. http://foo.bar/askme/anything/
  3. sftp://joe:secret@my.ftp.com

The above is more or less what we keep in out .tfvars files or in SSM secrets, because applications need to know the protocol and port, and path prefix, etc.

However, for appmesh, we also need to specify the backends to tell envoy to look up their definitions. This is where we need to strip stuff and just leave the domain name. And there's no way to do this in terraform, so we have to split our variables into separate protocols, auth, domain, path etc. It's doable, but could be much easier if there was an urlparse() function in terraform.

@nibblesnbits
Copy link

I'd love this, too. I need to set a DNS record based on an output that can only be a full URL. Without the ability to natively extract the Authority from that full URL, I can't automate my deployment properly.

@flynnhandley
Copy link

I'll have a crack at it @nibblesnbits

@flynnhandley
Copy link

flynnhandley commented Dec 4, 2022

@nibblesnbits @mkielar @apparentlymart

Would you mind reviewing this draft PR? If everyone's happy, I'll finish off the docs and convert it to a PR.

#32328

Thanks 🏖️

@speller
Copy link

speller commented Oct 23, 2023

Any updates here?

@bflad
Copy link
Member

bflad commented Oct 23, 2023

While I cannot speak to whether this might land as a built-in function in the Terraform configuration language, you might find #27696 an interesting issue to track.

@speller
Copy link

speller commented Oct 24, 2023

@bflad already tracking it :)
BTW, this time I needed to extract the host and port from AWS RabbitMQ's endpoint string returned in the URL form.

@hanswesterbeek
Copy link

@bflad already tracking it :) BTW, this time I needed to extract the host and port from AWS RabbitMQ's endpoint string returned in the URL form.

same here :)

@crw
Copy link
Collaborator

crw commented Mar 7, 2024

Thank you for your continued interest in this issue.

Terraform version 1.8 launches with support of provider-defined functions. It is now possible to implement your own functions! We would love to see this implemented as a provider-defined function.

Please see the provider-defined functions documentation to learn how to implement functions in your providers. If you are new to provider development, learn how to create a new provider with the Terraform Plugin Framework. If you have any questions, please visit the Terraform Plugin Development category in our official forum.

We hope this feature unblocks future function development and provides more flexibility for the Terraform community. Thank you for your continued support of Terraform!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.