Is there a standard way to get all possible (excluding wildcards of course) routes / paths valid within a play application ?
I can do it with
Play.current.routes.map( _.documentation.map(_._2))
which gives me all available routes but it looks a bit hacky to me.
Just for elaboration, what I do is this ( exactly what you did ):
val myroutes = Play.current.routes map (routes => routes.documentation) getOrElse (Nil)
myroutes foreach { r =>
println("%-10s %-50s %s".format(r._1, r._2, r._3))
}
And I also get:
GET / controllers.Application.index
GET /apis controllers.Application.apis
GET /docs controllers.Application.docs
GET /sampleapi/status/$id<[^/]+> controllers.SampleAPI.status(id:String)
GET /city/$id<[^/]+> controllers.CityAPI.findById(id:Long)
GET /city1/$id<[^/]+> controllers.CityAPI.findById1(id:Long)
GET /apps/authorize/ controllers.Apps.authorize
POST /apps/send_auth/ controllers.Apps.send_auth
GET /clients/ controllers.Clients.list
GET /client/new controllers.Clients.create
POST /client/add controllers.Clients.add
POST /client/update controllers.Clients.update
GET /client/edit/$id<[^/]+> controllers.Clients.edit(id:String)
PUT /client/ controllers.Clients.update
GET /client/$id<[^/]+> controllers.Clients.get(id:String)
DELETE /client/$id<[^/]+> controllers.Clients.delete(id:String)
GET /login controllers.Auth.login
POST /authenticate controllers.Auth.authenticate
GET /logout controllers.Auth.logout
POST /oauth2/access_token controllers.OAuth2Controller.accessToken
GET /webjars/$file<.+> controllers.WebJarAssets.at(file:String)
GET /assets/$file<.+> controllers.Assets.at(path:String = "/public", file:String)
This also includes webjar and assets path, so you may want to filter them out.
Related
I am facing this issue connecting with Facebook's API using httr package, while testing on 'me' node I came along the following problem.
I was under the impression that me node does not require special permissions.
Testing on the browser with 'https://graph.facebook.com/me' gave the same results, it would be great if some one could provide an explanation.
# Define keys
app_id = 'my_app_id'
app_secret = 'my_app_secret'
# Define the app
fb_app <- oauth_app(appname = "facebook",
key = app_id,
secret = app_secret)
# Get OAuth user access token
fb_token <- oauth2.0_token(oauth_endpoints("facebook"),
fb_app,
scope = 'public_profile',
type = "application/x-www-form-urlencoded",
cache = TRUE)
response <- GET("https://graph.facebook.com",
path = "/me",
config = config(token = fb_token))
# Show content returned
content(response)
$error
$error$message
[1] "An active access token must be used to query information about the current user."
$error$type
[1] "OAuthException"
$error$code
[1] 2500
$error$fbtrace_id
[1] "ARRnb93rZHmWLlXK_MMJlfi"
Noting that I have signed in using the app.
I'm not very savvy with web API calls, but I've been using the following powershell code (this site in this example is one I found that has some public data... my site is internal and requires I pass the credential, which has been working for me without issue):
If(-not (Get-InstalledModule -Name 'ConfluencePS')){Install-Module ConfluencePS}
Import-Module ConfluencePS
Set-ConfluenceInfo -BaseUri "https://wiki.opnfv.org"
$space = Get-confluencepage -Spacekey ds
ForEach($item in $space)
{
$splatParams = #{
Uri = "https://wiki.opnfv.org/rest/api/content/$($item.ID)/restriction"
ContentType = 'application/json'
method = 'GET'
}
#reference https://developer.atlassian.com/cloud/confluence/rest/#api-api-content-id-restriction-get
Invoke-RestMethod #splatParams
}
The documentation for the ConfluencePS shows that restrictions is still an open feature request but I need to get this working for a project.
I put a breakpoint in on line 982 from ConfluencePS.psm1 and was able to see the various calls and how the params are structured but when I try to mimic it (and change the URI based on the confluence documentation) I get an error "HTTP error 405 - MethodNotAllowed". Anyone have suggestions on how I can get this working? I'm trying to return back the permissions applied for all pages in a specific space.
Get Restrictions by Content ID
As you found out by yourself, it is required to add "byOperation".
I was able to get the restrictions of a specific page with the following code:
# for testing purposes ONLY, I've specified the URL and ID
$wikiUrl = "https://wiki.opnfv.org"
$itemId = "6820746"
$splatParams = #{
Uri = "$wikiUrl/rest/api/content/$itemId/restriction/byOperation"
ContentType = 'application/json'
method = 'GET'
}
$result = Invoke-RestMethod #splatParams
Tested on version 6.0.4 and 6.15.9
Filter by user name
If you like to filter the result by a specific username, you can use the following URI:
"$wikiUrl/rest/api/content/$itemId/restriction/byOperation/.../user?userName=".
Bt, there's an open bug on this way of action:
restriction returns ambiguous responses
I'm trying to get around a CORS error for a simple "hello world" style REST API in Scala/Play 2.6.x and I have tried everything that I can think of at this point. As far as I can tell there is not a good solution or example to be found on the internet, so even if this should be an easy fix then anyone that has a good solution would really help me out by posting it in full. I am simply trying to send a post request from localhost:3000 (a react application using axios) to localhost:9000 where my Scala/Play framework lives.
THE ERRORS
The error that I am getting on the client-side is the following:
XMLHttpRequest cannot load http://localhost:9000/saveTest.
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access. The response had HTTP status code 403.
The error that I am getting on the server-side is
success] Compiled in 1s
--- (RELOAD) ---
[info] p.a.h.EnabledFilters - Enabled Filters
(see <https://www.playframework.com/documentation/latest/Filters>):
play.filters.csrf.CSRFFilter
play.filters.headers.SecurityHeadersFilter
play.filters.hosts.AllowedHostsFilter
play.filters.cors.CORSFilter
[info] play.api.Play - Application started (Dev)
[warn] p.f.c.CORSFilter - Invalid CORS
request;Origin=Some(http://localhost:3000);
Method=OPTIONS;Access-Control-Request-Headers=Some(content-type)
MY CODE
I have the following in my application.conf file
# https://www.playframework.com/documentation/latest/Configuration
play.filters.enabled += "play.filters.cors.CORSFilter"
play.filters.cors {
pathPrefixes = ["/"]
allowedOrigins = ["http://localhost:3000", ...]
allowedHttpMethods = ["GET", "POST", "PUT", "DELETE"]
allowedHttpHeaders = ["Accept"]
preflightMaxAge = 3 days
}
I've tried changing pathPrefixes to /saveTest (my endpoint), and tried changing allowedOrigins to simply 'https://localhost'. I've tried changing allowedHttpHeaders="Allow-access-control-allow-origin". I've tried setting allowedOrigins, allowedHttpMethods, and allowedHttpHeaders all to null which, according to the documentation (https://www.playframework.com/documentation/2.6.x/resources/confs/filters-helpers/reference.conf) should allow everything (as should pathPrefixes=["/"]
My build.sbt is the following, so it should be adding the filter to the libraryDependencies:
name := """scalaREST"""
organization := "com.example"
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.12.2"
libraryDependencies += guice
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.0" % Test
libraryDependencies += filters
According to documentation available here: https://www.playframework.com/documentation/2.6.x/Filters#default-filters you can set the default filters like this:
import javax.inject.Inject
import play.filters.cors.CORSFilter
import play.api.http.{ DefaultHttpFilters, EnabledFilters }
class Filters #Inject()(enabledFilters: EnabledFilters, corsFilter: CORSFilter)
extends DefaultHttpFilters(enabledFilters.filters :+ corsFilter: _*)
I'm not sure exactly where that should go in my project - it doesn't say, but from other stackoverflow answers I kind of assume it should go in the root of my directory (that is /app). So that's where I put it.
Finally, there was one exotic stackoverflow response that said to put this class in my controllers and add it as a function to my OK responses
implicit class RichResult (result: Result) {
def enableCors = result.withHeaders(
"Access-Control-Allow-Origin" -> "*"
, "Access-Control-Allow-Methods" ->
"OPTIONS, GET, POST, PUT, DELETE, HEAD"
// OPTIONS for pre-flight
, "Access-Control-Allow-Headers" ->
"Accept, Content-Type, Origin, X-Json,
X-Prototype-Version, X-Requested-With"
//, "X-My-NonStd-Option"
, "Access-Control-Allow-Credentials" -> "true"
)
}
Needless to say, this did not work.
WRAP UP
Here is the backend for my current scala project.
https://github.com/patientplatypus/scalaproject1/tree/master/scalarest
Please, if you can, show a full working example of a CORS implementation - I cannot get anything I can find online to work. I will probably be submitting this as a documentation request to the Play Framework organization - this should not be nearly this difficult. Thank you.
Your preflight request fails because you have a Content-Type header set
Add content-type to allowedHttpHeaders in your application.conf like so
#application.conf
play.filters.cors {
#other cors configuration
allowedHttpHeaders = ["Accept", "Content-Type"]
}
I had this problem too and I added these code in application.conf
play.filters.enabled += "play.filters.cors.CORSFilter"
play.filters.cors {
allowedHttpMethods = ["GET", "HEAD", "POST"]
allowedHttpHeaders = ["Accept", "Content-Type"]"
}
and now everything is OK!
for more info
For playframework version 2.8.x , we can wrap the Response in a function as below -
def addCorsHeader (response : Result) : Result = {
response.withHeaders(
("Access-Control-Allow-Origin", "*"),
("Access-Control-Allow-Methods" , "GET,POST,OPTIONS,DELETE,PUT")
)
}
Now in the controller, wrap the Results using the above function.
val result = myService.swipeOut(inputParsed)
addCorsHeader(Ok(s"$result row successfully updated. Trip complete"))
}
else {
addCorsHeader(InternalServerError("POST body is mandatory"))
}
I am writing a test with PHPBowser, in Codeception v2.2.11 that uses the hidden API method of _loadpage.
I have added this into my \Helper\Api as follows:
public function loadpage($link)
{
$this->getModule('PhpBrowser')->_loadPage('POST', $link);
}
And call it in an Api Codeception test, as follows:
$link = 'http://www.fiercebiotech.com/contact';
$I->loadpage($link);
The issue I am facing is that when using _loadpage, it does not follow redirects. This exampled link when finally resolved is 301 redirected to:
http://www.fiercebiotech.com/contact-us.
Here is the header response console output when _loadpage opens $link.
I loadpage "http://www.fiercebiotech.com/contact"
[Request Headers] []
[Page] http://www.fiercebiotech.com/contact
[Response] 404
I need help getting _loadpage to not stop at ~/contact but follow the 301 redirect to ~/contact-us, so I can get the output header response to be
[page] http://www.fiercebiotech.com/contact-us
[response] 200
Currently I cant get _loadpage to follow 301 redirects. Anyone out there have success doing so?
Ive attempted to use Codeception REST function startFollowingRedirects and adding allow_redirects: true as follows, but neither technique seems to work (as the redirect is not followed).
class_name: ApiTester
modules:
enabled:
- WebDriver:
url: ''
browser: 'chrome'
window_size: 1200x993
clear_cookies: true
allow_redirects: true
- \Helper\Acceptance
- REST:
url: 'host'
depends: PhpBrowser
allow_redirects: true
- \Helper\Api
I found the solution to my issue:
The issue began with, as I suspected is that _loadpage does not follow redirects, it only loads the page requested and stops. In this case '~/contact-us', ignoring the fact that the page gets redirected to (with a 301) to '~/contact-us'.
I cant simply load the page (via _loadpage)
Get the header response
and assume that I will be getting the header response of the redirected URL
I will only get the header response of the original URL.
The Solution:
I have to in my foreach loop:
Go to the URL
send a GET
Grab the HTTP Header
Assert that the HTTP header has a 200OK response
Solution - As it is in Codeception code:
public function Validate_httpStatus_mainNav($mainNavLocator)
{
//Used to test main navigation -- 404 tests
$I = $this;
$mainNavLinks = $I->grabMultiple($mainNavLocator, 'href');
codecept_debug($mainNavLinks);
foreach ($mainNavLinks as $link) {
$I->amOnUrl($link);
$I->sendGET($link);
$I->grabHttpHeader($link);
$I->canSeeResponseCodeIs(HttpCode::OK);
}
}
I am new to Scala and Spray. I have written a simple REST API according to the instructions given in this blog post.
http://www.smartjava.org/content/first-steps-rest-spray-and-scala
And all are working as expected.
Now I want to modify the program to print the HTTP headers like Encoding, Language, remote-address, etc.. I would like to print all the header information (purpose is to log these information)
But I could not find a proper documentation or examples. Could anyone please help me to get this done.
If you need to extract a specific header:
optionalHeaderValueByName("Encoding") { encodingHeader =>
println(encodingHeader)
complete("hello")
}
alternatively you can access the raw request object and directly extractive the headers. Here's a custom directive that logs all the headers:
def logHeaders(): Directive0 = extract(_.request.headers).map(println)
Usage
logHeaders() {
complete("hello")
}
Here's how I got it working.
Directive:
def logHeaders(innerRoute: Route): (RequestContext => Unit) = extract(_.request.headers) { headers =>
headers.foreach(h => logger.info("header: {} = {}", h.name, h.value))
innerRoute
}
Usage:
logHeaders() {
complete("hello")
}