Mocked request doing actual requests call, not mock - requests-mock

I am mocking a get request in my unittest code using requests-mock, but when I run the code during testing, it still tries to hit the actual URL instead of returning the mocked data.
This is my code:
try:
response = requests.get(api_url, auth=requests.auth.HTTPBasicAuth(username, password))
response.raise_for_status()
except requests.ConnectionError as e:
raise dke.CLIError(f"Could not connect to Artifactory server to get NPM auth information: {str(e)}")
This is my test code
class MyTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
m = requests_mock.Mocker()
m.get('https://artifactory.apps.openshift-sandbox.example.com/artifactory/api/npm/auth',
text=("_auth = base64string==\n"
"always-auth = true\n"
"email = shareduser#fake.com"))
The api_url in my code matches the URL I pass to m.get(). However, when I run the test, I do not get the value of "text" but instead I get a 401 Client Error: Unauthorized and a response from the server indicating "Bad credentials" which tells me it actually tried to contact the server instead of returning the text I had requested in the Mock.
I'm lost. As far as I can tell, I'm using this exactly as the docs indicate. Any ideas?

So, it seems you can't use the request_mocker that way. It has to be a decorator or context manager.

I mean the context manager/decorator is just a pattern around normal code. I haven't tested it but i think you just have to call m.start()/m.stop().
It's generally used as a context manager or decorator because if you instantiate it once like that then your request history is going to include all requests across all unit tests which is very hard to make assertions about.

Related

add details to to HTTP response when eceiving HTTP requst

I have created a logic app to receive an http request and validate the content which is fine. But when I receive the 400 error message, it said only that it was expecting an integer but received a string for example. I would like to add the name of the field that generates the error is it possible?
postman response
I added an http response to be executed when the requst fails but it's never triggered.
logic flow
You can assign http response to a variable and then you can check which filed is causing error.
I have reproduced issue from my side and below are steps I followed,
Initially created logic app as shown below,
Payload of http trigger is,
Logic app trigger is enabled with schema validation,
I have tried to run trigger with below payload,
{
"number":1600,
"street_name":"pennsylvania",
"street_type":7
}
Got error "Failed to start a run of logic app alertschlapp. The input body for trigger 'manual' of type 'Request' did not match its schema definition. Error details: 'Invalid type. Expected String but got Integer.'."
Next modified logic app as shown below,
Added three initialize variables action for number, street_name and street_type
number:
street_name:
street_type:
Ran the logic app with below payload,
"number":1600,
"street_name":"pennsylvania",
"street_type":7
Logic app failed with below error,
In this way, you can find out which field value is causing issue.

Is it possible to obtain an access_token with expo-auth-session/providers/google?

I am trying to obtain an access token for use with Google APIs using the up-to-date expo-auth-session package.
It works fine to fetch an id_token via useAuthRequest({responseType: "id_token", ...}) or useIdTokenAuthRequest({...})
However, when trying useAuthRequest({responseType: "code", ...}), I get the following error:
[Unhandled promise rejection: Error: The request is missing a required parameter, includes an unsupported parameter value (other than grant type), repeats a parameter, includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed.]
Does anyone know what is missing from the request? I am using the Expo Go app currently, so I'm not sure if that prevents obtaining an access token. Currently digging through the package's source code...
Add the following two props to useAuthRequest
shouldAutoExchangeCode: false,
clientSecret: 'any_bogus_value!'
shouldAutoExchangeCode will prevent the code from being exchanged and send it back to you in the response.
clientSecret will simply trigger and if check to be true in the providers source code that will avoid that error you specified being returned.
Note that in general it is not a good practice to avoid errors, but in this case, I feel like the error is being shown in error itself!

How to fix "invalid return_url" error when creating oauth token for Trello with httr?

I want to manage my Trello cards and boards using the trelloR package but when I try to create a token with the get_token function, I get an error message on my browser : "Invalid return_url".
my_token <- get_token(key = my_key, secret = my_secret)
my_key is my personal Trello API key and my_secret is my OAuth secret. I got them on the Trello page that gives you your authentication codes, after login : https://trello.com/app-key
To use the Trello API and to access to boards, I need a token. This token is generated with OAuth1.0 by the httr package. Indeed, the function get_token do something like this, according to Jakub Chromec, author and maintainer of trelloR here :
trello.app = httr::oauth_app(
appname = "trello-app",
key = my_key,
secret = my_secret)
trello.urls = httr::oauth_endpoint(
request = "OAuthGetRequestToken",
authorize ="OAuthAuthorizeToken?scope=read&expiration=30days&name=trello-app",
access = "OAuthGetAccessToken",
base_url = "https://trello.com/1")
httr::oauth1.0_token(
endpoint = trello.urls,
app = trello.app)
When I execute this code or the function get_token with my personal key and secret, I am redirected to my browser, which is normal. As described on this page, a screen should appear asking me to allow authentication. But instead I just have an error message in the browser : "Invalid return_url".
In the RStudio console, this remains displayed :
> my_token <- get_token(my_key, my_secret)
Waiting for authentication in browser...
Press Esc/Ctrl + C to abort
I'm using httr 1.4.1, curl 4.2 and trelloR 0.6.0 with R 3.6.1 under macOS 10.15.
Some people reported the problem started after the introduction of Allowed Origins and they were able to fix it by adding the following origin:
http://localhost:1410
on the appkey page. This is a bit surprising to me as the default * should cover all origins, but there you go.
Trying this today (11/23/2019), I could not get wildcards to work as Allowed Origins. You should specify the domain of where you are running the call for authorization.
One source of confusion: The comments under "Allowed Origins" on https://trello.com/app-key refer to sites that "your application is allowed to redirect back to following the authorization flow." That was a bit confusing to me. The list should include sites you want to redirect back to IN ADDITION TO the sites you are calling Trello.authorize() from.
If you are thinking "I don't need a redirect" (and, in fact, if you are using client.js, I don't think you can specify a redirect), then those comments under "Allowed Origins" could lead you to believe you don't need to specify anything there. That would be incorrect.
Summary: Even if you want NO post-authorization re-direct, you still have to list an ORIGIN.
Also, you cannot specify file:// in Allowed Origins, so you cannot run your javascript off a local file.

How to stop consumers from hitting invalid resources in APIGee API

I have an Apigee proxy that has two resources (/resource1 and /resource2). If tried to access /resource3. How do I return a 404 error instead of the Apigee default fault?
Apigee displays the below fault string:
{
"fault": {
"faultstring": "The Service is temporarily unavailable",
"detail": {
"errorcode": "messaging.adaptors.http.flow.ServiceUnavailable"
}
}
}
Thanks
Currently the way flows work in apigee this way - It parses through your default.xml (in proxy) and tries to match your request with one of the flow either through the path-suffix like "/resource1, /resource2" or VERB or any other condition you might have. If it does not find any matching condition, it throws the error like above.
You can add a special flow which will be kicked in if the condition matches none of the valid flows you have. You can add a raisefault policy in that flow and add a custom error response through that flow.
A better solution is to:
be sure to define something in the base path of all Proxy APIs
create an additional Proxy API called "catchall" with a base path of "/" and with just a Raise fault throwing a 404
Apigee execute Proxy APIs from longest Base Path to shortest; the catchall will run last and always throw back a 404
I just want to clarify Vinit's answer. Vinit said:
If it does not find any matching condition, it throws the error like above.
Actually, if no matching flow condition is found, the request will still be sent through to the backend. The error you mentioned:
{
"fault": {
"faultstring": "The Service is temporarily unavailable",
"detail": {
"errorcode": "messaging.adaptors.http.flow.ServiceUnavailable"
}
}
}
was returned after attempting to connect to the backend without matching a flow.
Vinit's solution to raise a fault to create the 404 is the best solution for your requirements.
In some cases, however, it is appropriate to pass all traffic through to the backend (for example, if you don't need to modify each resource at the Apigee layer, and you don't want to have to update your Apigee proxy every time you add a new API resource). Not matching any flow condition would work fine for that use case.

How do I log asynchronous thin+sinatra+rack requests?

I'm writing my first Sinatra-based web app as a frontend to another TCP-based service, using EventMachine and async_sinatra to process incoming HTTP requests asynchronously. When I'm testing my app, all requests to synchronous routes are logged to stdout in common log format, but asynchronous requests are not.
I've read through bits of the source code to async_sinatra, Sinatra, Thin, and Rack, and it looks like logging of synchronous requests is done through CommonLogger#call. However, I can't find anywhere in the asynchronous code in async_sinatra or Thin that seems to pass asynchronous requests through the logging middleware (I'm looking at Sinatra::Helpers#body in async_sinatra and at Thin::Connection.post_process which is written into env['.async_callback'] in Thin's connection.rb:68 and request.rb:132).
I'm experienced with C but relatively new to Ruby, so if I've used some terminology or notation incorrectly, please correct me. Thanks in advance.
Edit: this also affects error handling. If an exception is raised in an asynchronous request, the request is never finished and the error is never logged.
I eventually found that using rack-async with async_sinatra was causing problems with 404 pages, exception handling, and logging:
!! Unexpected error while processing request: undefined method `bytesize' for nil:NilClass
Instead I used the following wrapper around aroute for logging:
module Sinatra::Async
alias :oldaroute :aroute
def aroute verb, path, opts = {}, &block
# Based on aroute from async_sinatra
run_method = :"RunA#{verb} #{path} #{opts.hash}"
define_method run_method, &block
log_method = :"LogA#{verb} #{path} #{opts.hash}"
define_method(log_method) { |*a|
puts "#{request.ip} - #{status} #{verb} #{path}"
}
oldaroute verb, path, opts do |*a|
oldcb = request.env['async.callback']
request.env['async.callback'] = proc { |*args|
async_runner(log_method, *a)
oldcb[*args]
}
async_runner(run_method, *a)
end
end
end
This is for the same versions of async_sinatra, Thin, and Rack that I was using when I asked this question last year; newer versions may allow the use of common Rack middleware for logging.
I am running on sinatra-synchrony and therefore I have a slightly different core than you.
But basically I solved the same problem.
Here is an abstract of the solution:
I am not using Rack::CommonLogger, I use my own Logger
You need to buffer log output in an async aware storage
The buffered log output must be flushed at the end of the request
In my sinatra-synchrony application I am running the following middleware for logging:
# in app.rb I register Logger::Middleware as the first middleware
use Logger::Middleware
# in logger.rb
module Logger
attr_accessor :messages
def log(message)
stack << message
end
def stack
# This is the important async awareness
# It stores messages for each fiber separately
messages[Fiber.current.object_id] ||= []
end
def flush
STDERR.puts stack.join("\n") unless stack.empty?
messages.delete Fiber.current.object_id
end
extend self
class Middleware
def initialize(app)
#app = app
end
def call(env)
# before the request
Logger.log "#{env['REQUEST_METHOD']} #{env['REQUEST_URI']}"
result = #app.call(env)
# after the request
Logger.flush
result
end
end
end
Logger.messages = {} # initialize the message storage
Everywhere in the application I am able to use Logger.log("message") for logging.

Resources