Package: apie
Application Program Interface with EonsWhether you want to make aRESTful APIor a fully functional web app,apiewill help you build quickly and reliably: the eons way!APIE is built oneonsand usesEons Infrastructure Technologiesto deliver modular functionality just-in-time.The goal of developing http servers this way is to separate complex logic into a number of distinct, independent, and reusable Endpoints. This makes development easier through direct application of theUnix Philosophyand ensures your systems are intuitive for users to apply to novel contexts after learning them once.Installationpip install apieUsageTo run anapieserver simply:apieAPIE will bind to port 80 by default, which is not typically allowed for non-root users. In order to bypass this, you must use a different port. You can specify custom interface and port from the command line like so:apie--hostlocalhost--port8080You may also specify:authenticator- your chosen authentication modules (see below).clean_start- whether or not to nuke cached Endpoints on startup.dev- if true, will cause this to start in development mode as opposed to prod; more infobelowpreprocessor- an Endpoint to always run first; more infobelowapie.jsonAPIE will look for a file called "apie.json" in the directory it is launched from. If such is found, the configuration values from it will be read and processed in accordance with the eons library. For example,apie --clean_start Falseis the same asapiewith an apie.json containing{"clean_start": false}. Note, command line variables will override configuration file variables (which override environment variables).Here is an exampleapie.json:{"verbosity":3,"no_repo":true,"clean_start":false,"port":8080}ParallelismCurrently, APIE only supports single-threaded operation. However, if your Authenticator and all your Endpoints maintain REST compatibility, you can run as many replicas ofapieas you'd like!MethodsYou may use any of the following http methods:GETPOSTPUTDELETEPATCHDesignAuthorizationThe goal of authorizing requests is to prevent every api from becoming the same, since Endpoints are executed on-demand (see below), and to impose the obviously needed security.
If a request is not authorized, no Endpoint is called. This means you can limit which Endpoints are callable and who can call them.Each and every request must be authenticated. You may use whatever authentication system you want (including thenoauthandfrom_configmodules provided in theapiepackage).Your chosen authentication module must be of theauth_type if usingEons Infrastructure Technologies(the default repository).To create your own authorization system, check outauth_from_config.pyfor a starting point.NOTE: EveryAuthenticatorMUST returnTrueorFalse.API EndpointsEndpoints.../are/all/of/these?but=not-these; in other words each part of a request path is a separate Endpoint.To provide functionality,apiewill download the Endpoints for any request that is executed as part of processing that request.
To see where packages are downloaded from and additional options, check out theeons python library.Each Endpoint may modify the next by simply setting member variables and methods (per the eons implicit inheritance system). For example, you might have 3 Endpoints:package,photo, andupload; bothpackageandphotoset a member calledfile_data;uploadthenFetches (a method provided by eons) thefile_datavalue and puts it somewhere; you can thus useuploadwith either precursor (e.g..../package/uploadand.../photo/upload).This style of dynamic execution allows you to develop your API separately from its deployment environment (i.e. each module is standalone) and should make all parts of development easier.ReturnsOnly the last Endpoint is returned!This is done to ensure that all information given is intended. If you want to provide information in your response, grab that information from the precursors, usingFetch().Return values are automatically set from thethis.responsemember.All Endpoints may setthis.response.code: anhttp status codein the form of anint.EveryEndpointshould have athis.mimevalue. By default, it isapplication/json.For more on MIME Types, check out theMozilla documentation.If the mime type isapplication/json, the data that are inthis.response.content.datawill be converted into a json string upon return.Security and ValidationIn addition to authenticating each request, Endpoints may further restrict what can follow them via thethis.allowedNextmember (list).By specifying only a limited list of actions, even users who are allowed to call your Endpoint can't call things like.../something/legitimate/now_dump_all_user_passwords/k_thx_bye.You can add to theallowedNextmember byappend(...)ing to the list.You may also require only certain http methods be used with your Endpoint. This is for sanity more than security. Restricting thethis.supportedMethodsmember (also a list), you can prevent things likecurl -X DELETE host/create/my_resource. ThesupportedMethodsis prepopulated with all thehttp methods listed above. You can remove methods from this list withthis.supportedMethods.remove(...).Error HandlingAPIE itself keeps track of the last Endpoint it called. This allows that Endpoint to handle errors in its own execution.If you would like to add custom error handling, overrideHandleBadRequest()in your Endpoint. By default this will print the error message, per the python Exception and tells the user to call your Endpoint with/help(seebelow).SyntaxAPIE supports some unique syntax which can be specified in the request path.MultiA "Multicall" will make the same call for each element in a domain. This is essentially a foreach loop.Domains can be specified by prepending "[first_element,second_element]" to the desired Endpoint.Requirements:The first character must be a '['.Each element must be separated by a comma (',') WITHOUT a space (i.e. ', ' is wrong but ',' is right).The domain must end with a ']'There must be a valid Endpoint after the domain.For example,.../[public,private]listwould calllistfirst withpublic_prepended to all Fetched arguments, then likewise withprivate_. Iflistneeds a "url" arg, the first call would be made withpublic_urland the second would be made withprivate_url. The results of both would be combined (assuming the Content-Type is 'application/json') and a single list would be returned.For more information, see themulti Endpoint.While not yet tested, multi-multi calls should work. For example.../[one,two][red,blue]fishshould equate toone/red/fish,one/blue/fish,two/red/fish,two/blue/fish.Nested multicalls are not yet supported (e.g..../[one[red,blue],two['green','yellow']]fishwill not work at the moment).REST CompatibilityTo be "RESTful" means to abide the following principles.More information can be found atrestfulapi.netUniform interface"A resource in the system should have only one logical URI, and that should provide a way to fetch related or additional data"Each combination of Endpoints yields a unique execution path (e.g..../package/uploadoperates on different resources than.../photo/upload).Reusing the same Endpoint should provide the same functionality (e.g.uploadshould not start downloading things).Endpoints should not provide duplicate functionality (besides, don't write the same line of code twice anyway!)."Once a developer becomes familiar with one of your APIs, [they] should be able to follow a similar approach for other APIs."Client–server"Servers and clients may also be replaced and developed independently, as long as the interface between them is not altered."In addition to interacting with other machines over the net, the client-server paradigm is expanded to server-side processing through the use of standalone Endpoints. Each Endpoint should follow its own, independent development lifecycle and be interchangeable with any other Endpoint that provides the same up (preceding) and down (next) stream interfaces.Stateless"[The server] will treat every request as new. No session, no history."This part is optional and what ultimately defines RESTful compatibility in APIE.If you wish to maintain state, use a custom Authenticator as describedbelow."No client context shall be stored on the server between requests. The client is responsible for managing the state of the application."Cacheable"In REST, caching shall be applied to resources when applicable, and then these resources MUST declare themselves cacheable"To aid in caching, everyjsonEndpoint will declare itself as "cacheable" or not based on thethis.cacheablemember value. If your response can be cached client-side, setthis.cacheable = True(andthis.mime = 'application/json')Layered systemYou can make calls to any other services you'd like within your Endpoints and Authenticators.Code on demand (optional)"you are free to return executable code to support a part of your application"What you return is entirely up to you.Web Apps, User Sessions, and the Static AuthIf a RESTful application is inappropriate for your use case, you can still use apie. The only thing that changes is which Authenticator you employ. The Authenticator you choose is instantiated on startup, stored in theauthmember of APIE, and lasts the life of the program.Because the Authenticator checks each and every request, you can use it to change the path executed, store a history of the user's requests, etc.Both the Authenticator and each Endpoint can access apie from theexecutormember. This means each Endpoint has access to the the Authenticator (i.e.this.executor.auth).Combining all this, to make your app stateful, all you have to do is build an Authenticator to track the state you'd like.Testing, Debugging, and DevelopmentThere is a specialhackEndpoint that is enabled when apie is run with--dev True(or equivalent, e.g. "dev": true in config).Hacking allows you to mock the functionality of downstream Endpoints.This behavior is not fully implemented but will be available soon.Additional FeaturesPreprocessorYou can set an Endpoint to be run before any other and which will not be included in the request path by specifyingpreprocessor.For example, with{"preprocessor": "myapp"}in your apie.json, a call to.../access/whatever/would be silently expanded to.../myapp/access/whateverThis is useful if you want to change Endpoints to fit a scheme suitable to your deployment, gain extra introspection, and much more.HelpBy default, you can call.../anything/helpto get information on how to useanything. Data are returned as a json.From Config AuthenticatorIncluded in the apie package is thefrom_configAuthenticator. This allows you to store a static authentication scheme locally.This does not help with dynamic user access but does allow you to limit what Endpoints you allow access to.Resource ParadigmOne possible means of using apie is through the Resource Paradigm. This concept frames all apie requests as manipulations of resources.Resources can be anything but will generally be correlated with data structures of similar shape. For example, "user" might be a resource, where each user has a name, email, and password. These 3 fields define the shape of a user datum.Manipulations take place through Operations and Operation Implementations. Operations are simple and define a consistent interface for use across many different resources. For example, thelistoperation is always paginated, so you can.../user/list?page=2or.../whatever_else/list?per_page=100. The list operation itself simply defines what arguments can be provided, gives some standard help text for users, and establishes basic features. Howlistactually works is entirely dependent on the implementation specified in the apie configuration. For example, if youlistfiles stored on the server, you might use alocalimplementation to read and reply with inode data from the local filesystem; whereas, listing items from a database would use adatabaseimplementation, and so on.The apie resource paradigm looks something like: