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

Implement HTTP server REST API #182

Merged
merged 1 commit into from
Oct 21, 2016
Merged

Implement HTTP server REST API #182

merged 1 commit into from
Oct 21, 2016

Conversation

tribal-tec
Copy link
Contributor

  • added support for /schema and /registry endpoints
  • added ZeroEQHTTP target, moved from ZeroEQ library
  • rename subscribe() and register_() to handlePUT/GET accordingly
  • group RFCs in doxygen

eile
eile previously requested changes Oct 19, 2016
@@ -26,6 +32,30 @@ std::string _toLower( std::string value )
return value;
}

// http://stackoverflow.com/questions/5343190/how-do-i-replace-all-instances-of-a-string-with-another-string
Copy link
Contributor

Choose a reason for hiding this comment

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

Tip: you can remove the /how-.... part

{
subject.replace( pos, search.length(), replace );
pos += replace.length();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

can also be written as a for loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To gain what?

Copy link
Contributor

Choose a reason for hiding this comment

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

Because it is one. Precondition is before while, loop statement is at the end of the while scope. Not important, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not my implementation, hence the reference of origin. Worked at first shot, didn't take a second glance to make it even better.

GETFuncMap _registrations;
typedef std::map< std::string, std::string > SchemaMap;
PUTFuncMap _PUT;
GETFuncMap _GET;
Copy link
Contributor

Choose a reason for hiding this comment

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

why not lower-case variable names?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

looks more weird to me, but if you prefer


running = false;
thread.join();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing tests:

  • Object named Schema: 'GET /foo/schema', 'GET /foo/schema/schema'
  • Object named Registry: throw when registering without namespace, 'GET /foo/registry', 'GET /foo/registry/schema'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

should have been mentioned in the specification phase, now it's too late :)
Still not getting what exactly to test... there is already a test for garbage input, this is just structured garbage.

Copy link
Contributor

Choose a reason for hiding this comment

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

all GETs mentioned should return meaningful values, i.e., should not fail. I don't see in the spec that using an object named schema is forbidden, and I don't see a reason why it should be. idem for registry, except in the global namespace.

Copy link
Contributor Author

@tribal-tec tribal-tec Oct 19, 2016

Choose a reason for hiding this comment

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

object named schema is tested, registry can be implemented, although I miss the use-case. global namespace registry is implemented, probably we're talking about different things here.

Copy link

@rdumusc rdumusc left a comment

Choose a reason for hiding this comment

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

Looks good! However I thought we had decided to keep only a single remove() function and not the multitude of overloads of removePUT() and removeGET()? Somehow it does not figure in the spec, but I still don't see them as being especially useful.

event = _toLower( _replaceAll( event, "/", "::" ));
if( _put.count( event ) == 0 )
_schemas.erase( event );
return _get.erase( event ) != 0;
Copy link

Choose a reason for hiding this comment

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

style opinion # 2: I don't feel that the != 0 adds 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.

It's just correct code. As long as there are compilers whining about int-to-bool conversion, I'm not changing that style.

event = _toLower( event );
if( _registrations.count( event ) != 0 )
event = _toLower( _replaceAll( event, "/", "::" ));
if( _get.count( event ) != 0 )
Copy link

Choose a reason for hiding this comment

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

general style opinion: I find if( !_put.count( event )) more readable

Copy link

Choose a reason for hiding this comment

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

oops went to wrong place, should have been 3 lines below. Here it would be if( _get.count( event )) of course

Choose a reason for hiding this comment

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

I don't know if it's relevant, but MSVC used to whine about a potential performance bug in the implicit int to bool conversion if you do that.

const size_t pos = name.find( '/' );
if( pos == std::string::npos )
return name;
const std::string key = _replaceAll( i.first, "::", "/" );
Copy link

Choose a reason for hiding this comment

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

wouldn't it be more logical to store the keys with '/' directly? Only the servus::Serializable need a conversion at insertion time, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To me we could use '/' everywhere, also from the ZeroBuf code generator. I'm trying to be as less invasive as possible and not changing things w/o discussing them.

if( uri.length() < REQUEST_SCHEMA.length( ))
return false;
return uri.compare( uri.length() - REQUEST_SCHEMA.length(),
REQUEST_SCHEMA.length(), REQUEST_SCHEMA ) == 0;

Choose a reason for hiding this comment

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

second parameter can be std::npos

Copy link
Contributor Author

Choose a reason for hiding this comment

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

?

Copy link

@hernando hernando Oct 19, 2016

Choose a reason for hiding this comment

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

uri.compare( uri.length() - REQUEST_SCHEMA.length(),
             std::npos, REQUEST_SCHEMA ) 

}

const std::string REQUEST_REGISTRY = "registry";
const std::string REQUEST_SCHEMA = "schema";

Choose a reason for hiding this comment

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

No / before schema and registry?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The slash is stripped by _getTypeName(), so yes, no slash here.

ZEROEQ_API explicit Server();
ZEROEQ_API explicit Server( Server& shared )
ZEROEQ_API Server();
explicit Server( Server& shared )

Choose a reason for hiding this comment

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

ZEROEQ_API removed on purpose? If this function is internal tag it.

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 inline functions we typically have no FOO_API declaration.

Choose a reason for hiding this comment

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

I always forget about this.

}

return body.toStyledString();

Choose a reason for hiding this comment

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

If you have included the Jsoncpp source just to format the output of this response it's a bit of overkill in my opinion.

_subscriptions[ event ] = func;
_put[ event ] = func;
if( !schema.empty( ))
_schemas[ event ] = schema;

Choose a reason for hiding this comment

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

Throw if there's an schema and it's not the same (maybe a good reason to use jsoncpp, so you can compare schemas without failing due to whitespace)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You assume then that the schema is always JSON-formatted.

Choose a reason for hiding this comment

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

At least you should do a string comparison then. What does it mean to register GET and PUT with different schemas otherwise?

BOOST_CHECK( server.add( foo ));
BOOST_CHECK( !server.add( foo ));
BOOST_CHECK( server.handle( foo ));
BOOST_CHECK( !server.handle( foo ));
BOOST_CHECK( server.remove( foo ));
BOOST_CHECK( !server.remove( foo ));

Choose a reason for hiding this comment

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

Add tests to verify that the schema is not removed if you remove the PUT handler but a GET handler stays.

const std::string& exist = _returnSchema( event );
if( !exist.empty() && schema != exist )
ZEROEQTHROW( std::runtime_error(
"Schema registered for event differs: " + event ));
_schemas[ event ] = schema;

Choose a reason for hiding this comment

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

Do no reassign if already the same.

Copy link
Contributor

@eile eile left a comment

Choose a reason for hiding this comment

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

.

@tribal-tec
Copy link
Contributor Author

Good now?

@rdumusc
Copy link

rdumusc commented Oct 21, 2016

+1 for me despite my question about the removePUT/GETs has been ignored. I feel that we should have waited until (if?) we had a concrete need for so many methods, but as you wish :-)

@tribal-tec
Copy link
Contributor Author

The remove... methods are only for symmetry reasons I guess. None of our code removes events from the server, so not even a remove() is needed. I can remove (haha) them actually.

* added support for /schema and /registry endpoints
* added ZeroEQHTTP target, moved from ZeroEQ library
* rename subscribe() and register_() to handlePUT/GET accordingly
* group RFCs in doxygen
@tribal-tec tribal-tec merged commit 1019277 into HBPVIS:master Oct 21, 2016
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.

5 participants