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

Extend URI Parsing Specs #69

Merged
merged 7 commits into from
Dec 13, 2017
Merged

Conversation

Tensho
Copy link
Contributor

@Tensho Tensho commented Dec 11, 2017

Before we adopt URI query params in bunny and amqp, I'd like to polish specs for URI in amq-protocol. While I was investigating the code, I met some non-intuitive places that would like to discuss. I guess it's better to talk about them here in PR as far as I tackled required places, or at least start here and move to GitHub issues if needed.

# server
:host => "127.0.0.1",
:port => AMQ::Protocol::DEFAULT_PORT,
# Consider to move this defaults to client libraries (bunny, amqp, auto-generated amq-protocol client)
Copy link
Contributor Author

@Tensho Tensho Dec 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AMQ::Settings only holds defaults for the assumed clients and switch between Hash and String like options processing. In my opinion, all client specific parameters should be handled (validate, fallback to default, other conditional logic, etc.) exactly inside client code, not protocol library.

I'd like to propose to retire client specific options (frame_max) form AMQ::Settings module and leave only basic ones. "Basic" means all that standard Erlang client supports according to "URI Specification" and "URI query parameters" official RabbitMQ documentation page.

I doubt that localhost host or guest username should be setup at this abstraction layer. Instead they should be specified as the defaults on the client library side for the better convenience to use it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If all clients use the same defaults, why extract anything?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the sake of concerns separation. Underlying protocol library is not responsible for client specific features and should adopt them as plugins/extensions. The same is reasonable for the configuration I guess.

Copy link
Member

@michaelklishin michaelklishin Dec 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the settings are identical, are they really client-specific? What's the probability of them changing independently (e.g. in only one client or both to different values)? I'd say it's 0. Please stick to the changes we've discussed," concern separation" is a fantastic way of wasting a lot of time on something that you'd never get any real benefit from.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK :) I don't mind to stick with the current design, just announced my thoughts. I will proceed with bunny and amqp. Could we merge the specs extension in this PR anyway?

@@ -6,7 +6,10 @@
module AMQ
class URI
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think if we try to conform URI Ruby standard library hierarchy and extract separate AMP::URI::AMQP and AMP::URI::AMQPS classes?

amq uri

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any real benefit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could simplify the code and make it more object-oriented instead of procedural in my opinion. Because AMQP URI is just another kind of generic URI, contributors, that are familiar already with URI (especially as it's a standard library), intuitively could rely on known public API.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how having 4 new classes would simplify things. We are not preparing this library for inclusion into the standard library.

Moving classes and constants around means Bunny and amqp gem will have to be updated, and their older versions won't be compatible with newer version of amq-protocol, which has been the case for years.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry but "more object-oriented code" for a couple of constants is a solution in search of a problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, appreciate your open point of view, thank you 🙇

# server
:host => "127.0.0.1",
:port => AMQ::Protocol::DEFAULT_PORT,
# Consider to move this defaults to client libraries (bunny, amqp, auto-generated amq-protocol client)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should be deleted as these defaults won't move to Bunny and amqp gem.

let(:uri) { "amqp://" }

# Note that according to the ABNF, the host component may not be absent, but it may be zero-length.
it "fallbacks to default nil host" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"it falls back"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, will fix

context "schema amqp" do
let(:uri) { "amqp://rabbitmq" }

it "fallbacks to 5672 port" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

context "schema amqps" do
let(:uri) { "amqps://rabbitmq" }

it "fallbacks to 5671 port" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

context "only username present" do
let(:uri) { "amqp://alpha@rabbitmq" }

it "parses user and fallbacks to nil pass" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

context "with ':'" do
let(:uri) { "amqp://alpha:@rabbitmq" }

it "parses user and fallbacks to "" (empty) pass" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

context "only password present" do
let(:uri) { "amqp://:beta@rabbitmq" }

it "parses pass and fallbacks to "" (empty) user" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

context "with ':'" do
let(:uri) { "amqp://:@rabbitmq" }

it "fallbacks to "" (empty) user and "" (empty) pass" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

end
end

context "escaped" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you mean "%-encoded".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to method names in URI::Escape module of URI library, escaped and encoded mean the same. But your variant looks more descriptive and unambiguous ^_^

new:

- heartbeat
- connection_timeout
- channel_max
- auth_mechanism
- verify
- fail_if_no_peer_cert
- cacertfile
- certfile
- keyfile

rename:

timeout -> connection_timeout
Copy link
Contributor Author

@Tensho Tensho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, if amq-protocol is intended to handle defaults for bunny and amqp, why does Bunny::Session has it's own default constants, like DEFAULT_HOST, DEFAULT_PASSWORD, DEFAULT_HEARTBEAT, DEFAULT_CHANNEL_MAX?

@michaelklishin
Copy link
Member

Because Bunny is several years older than amqp-protocol.

@michaelklishin michaelklishin merged commit 645df33 into ruby-amqp:master Dec 13, 2017
@Tensho Tensho deleted the extend-uri-specs branch December 13, 2017 16:49
michaelklishin added a commit that referenced this pull request Dec 26, 2017
Percent encoding only applies to virtual hosts (URI paths).
CGI.unescape is the only non-deprecated way of %-decoding string
values so it can be applied to hostnames but different parts of URI
use different encoding schemes.

References #69.
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Mar 14, 2018
## Changes between 2.2.0 and 2.3.0 (Jan 8th, 2018)

### Support for Additional URI Query Parameters

GitHub issue: [#67](ruby-amqp/amq-protocol#67), [#68](ruby-amqp/amq-protocol#68), [#69](ruby-amqp/amq-protocol#69).

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

Successfully merging this pull request may close these issues.

2 participants