I want to extract a token either from the query parameter or the Authorization header.
For that, I created this directive:
(parameter("token".optional) | optionalHeaderValueByName("Authorization")).flatMap { _ match {
case Some(token) =>
// authenticate it
complete(...)
case None =>
reject(AuthenticationFailedRejection)
}
}
The issue is that requests with a "token" query parameter work, but requests that have the "Authorization" header (and no query parameter) don't. The optionalHeaderValueByName is skipped.
I believe it is because when parameter("token".optional) is rejected, it automatically returns a 401 Unauthorized response.
If that is indeed the case, is there a way I can make it so it also checks the optionalHeaderValueByName?
I thought that the | operator was made for this.
Maybe it works when returning a route? And not when flatMapping?
This post covers the same use-case: How do I use two Directives with OR in Akka-HTTP?
But for some reason, I can't replicate it.
Thanks.
I believe it is because when parameter("token".optional) is rejected, it automatically returns a 401 Unauthorized response.
I believe it's the opposite. You made "token" parameter optional, that means when it's absent it still will be accepted and the directive after | never evaluated. If you drop the .optional and token parameter is not there it will be rejected and directive after | will be evaluated.
Related
The project uses a swagger.
There is the following code.
#swagger_auto_schema(
manual_parameters=[
Parameter('download', IN_QUERY,
'Set `Content-Disposition=attachment` to make browser to download file'
'instead of showing it.',
type='bool'),
Parameter('share_id', IN_PATH, type='uuid')
],
security=[],
responses={'400': 'Validation Error (e.g. base64 is wrong)',
'200': VideoSerializer}
)
Please explain what each argument is responsible for.
I read the documentation, but understood little ...
Particularly interested in '200': VideoSerializer
responses
The responses argument is a dictionary of possible responses that this endpoint can return.
400 and 200 are HTTP response codes, Bad Request and OK respectively.
In this case, this means that this endpoint can generate two types of responses:
Bad request which will also return (as described) a Validation Error which means that something in the request was incorrect, which means it could not be handled correctly.
OK, which means the request is correct, and everything was handled correctly. VideoSerializer means that a response will be given with accordance to the structure of the VideoSerializer, which defines a collection of fields.
The other two arguments:
manual_parameters
This a custom list of parameters that can be added to the request to customize the response.
In this case, two parameters are defined:
download : A query parameter of type bool. Query parameters are passed like this : `example.com?query_parameter=true
share_id, a path parameter of type 'uuid'. Path parameters are passed like this : example.com/path_parameter
security
A list of security schemes that the request must adhere to. Used for instance for Basic authentication.
I need to make a request for a CSS file.
I know which folder on the server my file will be in.
What I don't know is the exact file name. It will be titled of the form theme.bundle.xxxxxxxxxxxxxx.css where xxxxxxxxxxxxxx is a series of random characters and numbers generated at build time.
My question is, is it possible to make an HTTP request with a regex to get the name of the matching file(s)? I don't need help constructing the regex itself, but rather how to utilize one in combination with an HTTP request.
I can't find any information related to the usage of regular expressions to construct an HTTP request, or if this is even possible.
Short answer: Not possible, unless you have access to customize your server. You tagged this question as an "angular" question. From an Angular standpoint - Angular can't make this happen.
Longer answer: Totally possible! But this ends up being more of a backend question, not an Angular question. You didn't specify which backend you have, so I'll use a Node/Express server as an example. Part of building a server is setting up routing and API endpoints. Consider this code that responds with a particular file whenever the server receives a GET request to /images/background
app.get('/images/background', function(req, res) {
res.sendFile('public/img/background.png')
})
For your situation, you would need to set up an endpoint with similar logic to this:
app.get('/getMyCssFile', function(req, res) {
// Use NodeJS fs module to loop over files in /testfolder and read the file names
let matchingFile;
fs.readdirSync(testFolder).forEach(file => {
console.log(file);
// Perform REGEX matching here, if filename matches, then save this file name
if (matches) {
matchingFile = file;
}
})
if (matchingFile) {
res.sendFile(file)
} else {
// handle sending error - no matching file found
}
})
On your Angular frontend, you'd just need to request /getMyCssFile, and your server will respond with the matching file.
I'm trying to use circe to do my JSON (de)serialization in an Akka-Http app, rather than spray-json. For that reason, I want to use the entity directive with as[String] to get the string representation of the request body, and then do my own deserialization. But it seems that entity is too smart for its own good, and is rejecting anything that does not have the Content-Type text/plain.
My understanding from the docs is that implicit magic should let me be able to do something like:
import akka.http.scaladsl.model.ContentTypes
entity(as[String].forContentTypes(ContentTypes.`application/json`))
But the compiler is not doing the whole thing of inferring that I want as to resolve to a FromEntityUnmarshaller[String], which has that implicit method forContentTypes, whose result should be converted to a FromMessageUnmarshaller[String], which (due to contravariance) should satisfy the need for a FromRequestUnmarshaller[String].
However, even holding the compilers hand by doing:
val jsonRequestToStringUnmarshaller: FromRequestUnmarshaller[String] =
messageUnmarshallerFromEntityUnmarshaller(implicitly[FromEntityUnmarshaller[String]].forContentTypes(ContentTypes.`application/json`))
entity(jsonRequestToStringUnmarshaller)
my server is still rejecting application/json requests.
What gives?
Update
I can see now that I misunderstood forContentTypes, and that it will only narrow, not expand, the Content-Type range that an Unmarshaller will accept. That just explains why my solution isn't working.
I would suggest to give Akka-Http direct marshallers-unmarshallers from / to desired types using circe under the hood.
It may look like: https://github.com/PDXostc/rvi_sota_server/blob/master/common/src/main/scala/org/genivi/sota/marshalling/CirceMarshallingSupport.scala
Using the latest versions of Flask and Flask-RESTful, I have some very basic routes defined as such:
def build_uri_rules(uri_map):
for cls, uri in uri_map.iteritems():
api.add_resource(cls, uri)
uris = {
SampleController: '/samples/<string:hash_or_id>',
SampleFamilyController: '/samples/<string:hash_or_id>/family',
}
build_uri_rules(uris)
This works for uris requested 'properly', but what if the /samples/ endpoint is hit without a parameter, or the sample*family endpoint is hit with an empty sample id? Currently, this results in a 404 error. This works well enough, but I believe the proper thing here would be to throw a 400 error, as they found a proper URL but their data is improperly structured. Is there a way that I can force this behavior?
As a side note:
Looking through the Werkzeug docs, I see that werkzeug.routing allows a minimum length for certain url parameters, but I also see that it's got a minimum of 1. Admittedly, I've not look for why this is the case, but would this be the right tree to bark up? or should I rather simply create a global 404 handler that checks for the length of the parameter and raise the proper error from there?
Thanks!
EDITED: For code correctness.
I would say that hitting /samples/ or /samples/family (or even /samples//family) should result in a 404 as there is nothing at that endpoint.
If, however, you want to do otherwise, the simplest way to handle it would be create a 404 handler for just /samples/ and /samples/family that returns a note with more information about what the consumers of your API are most likely doing wrong.
uris = {
Explanitory400Controller: '/samples/',
SampleController: '/samples/<string:hash_or_id>',
Explanitory400Controller: '/samples/family',
SampleFamilyController: '/samples/<string:hash_or_id>/family',
}
I have the following Url which returns me the list of resources:
http://example.com/resources/
I also implemented a method which returns a specific resource (in this case, the resource 142).
http://example.com/resources/142
I would like to add a method which is outside the typical HTTP method: List, Create, Retrieve, Replace, Update. What is the pattern to follow? In my specific case, I need to check the availability of resource. How would the Url look like (http://example.com/resources/checkavailability/142)?
I though about simply using the GET method and retrieve that information as part of the object returned. However, some of my colleagues argue that this would not be efficient (the data to transfer would be much bigger than just returning true/false).
Thanks for the help!
There is no need for a resource to check the availability of another resource, and there is no need for a GET request, a HEAD request should be enough, this is the same as a GET request but without transferring the body. You can then look at the return codes, and via those determine if the resource is available. This is assuming you have properly implemented return codes.
Restful over HTTP gives you uniform interface, you often don't need to encode the actions inside your URL
Regarding your mentioned /checkavailability using GET returning payload inefficiency is a valid reason, so use HEAD (it only gives you back the response headers).
request:
HEAD /resources/123
response status:
404 Not Found: equals to /checkavailability == false
200 OK: equals to /checkavailability == true
Other suggestions uniform interface replacements:
/resources/list : GET /resources
/resources/replace/123: PUT /resources/123
/resources/update/123: PUT /resources/123
/resources/create: POST /resources