Expiring api request caches - ruby-on-rails-3

I've implemented API caching based on http://robots.thoughtbot.com/caching-api-requests. I'm using memory as the storage. How can I reset the cache manually without restarting the server?
I've tried using Rails.cache.clear, but it doesn't seem to work. The data is still getting pulled from the cache. I checked it by observing the server log for my puts message (as shown below).
Caching code:
module Meh
class Api
include HTTParty
#...
cache_name = options[:path] + "/" + options[:params].values.join(",")
response = nil
APICache.get(cache_name, cache: 3600) do
response = self.class.get options[:path], query: options[:params]
# For future debugging
puts "[API] Request: #{response.request.last_uri.to_s}"
# Just return nil if there's an error with the request, for now
if response.code == 200
response.reverse!
else
response = nil
end
end
end

Have you tried 'rake tmp:cache:clear' or deleting the contents of tmp/cache/ manually?
Are you trying to delete the contents of the cache from within the code?
Reading through the api_cache gem, it looks like this is a memory cache, not a file cache. Which would be consistent with your reports. It also looks like there is a .delete method on the APICache api. link So APICache.delete(cache_name) may be what you are looking for.

Related

How to stop further routing in a plug?

I'm using Phoenix, and in router.ex, I have defined a function that verifies the user's JWT token, before continuing on to routing through the api, in order to protect the routes. However, I am having the issue that if, say, I return a status of 403 in the plug, it continues routing and I end up getting an error as I am both accessing the route and disallowing access.
My code looks something like this:
def validate(conn, _opts) do
if !Map.has_key?(conn.cookies, "jwt") do
conn
|> send_resp(403, "Forbidden")
# I would like to have something here that stops further
# routing - i.e. a way to say 'already sent a response; don't keep going'
end
end
Here is an excerpt from Plug.Conn.send_resp/3
Note that this function does not halt the connection, so if subsequent plugs try to send another response, it will error out. Use halt/1 after this function if you want to halt the plug pipeline.

CSRF failure in custom mongoose pre-hook (Keystone.js)

using keystone LocalFile type to handle image uploads. similar to the Cloudinary autoCleanup option, I want to be able to delete the uploaded file itself, in addition to the corresponding mongo entry when deleting entries through the admin ui.
in this case, I want to delete an "Album", and it's corresponding album cover.
Album.schema.pre('remove', function(next){
var path = this._original.album_cover.path + "/" + this._original.album_cover.filename
fs.unlink(path, function () {
console.log('deleted');
})
I get "CSRF failure" when using the fs module. I thought all CSRF protection was handled internally with Keystone.
Anyone know of a better solution to this?
Took a 10 minute break and came back and it seems to be working now. I also found this, which seems to be the explanation.
"Moreover double check your session timeout. In my dev settings the session duration is set to 3 minutes. So, if I end up editing something for more than that time, Keystone will return a CSRF error on save because the new session (generate in the meantime) invalidates the old token."
https://github.com/keystonejs/keystone/issues/1330

Problems Connecting to MtGox API 2 with Python

I am writing a trading program that I need to connect to MtGox (a bitcoin exchange) through the API v2. But I keep getting the following error:
URL: 1 https://data.mtgox.com/api/2/BTCUSD/money/bitcoin/address
HTTP Error 403: Forbidden.
Most of my script is a direct copy from here (that is a pastebin link). I just had to change it to work with Python 3.3.
I suspect that it has to do with the part of script where I use base64.b64encode. In my code, I have to encode my strings to utf-8 to use base64.b64encode:
url = self.__url_parts + '2/' + path
api2postdatatohash = (path + chr(0) + post_data).encode('utf-8') #new way to hash for API 2, includes path + NUL
ahmac = base64.b64encode(str(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest()).encode('utf-8'))
# Create header for auth-requiring operations
header = {
"User-Agent": 'Arbitrater',
"Rest-Key": self.key,
"Rest-Sign": ahmac
}
However, with the other guy's script, he doesn't have too:
url = self.__url_parts + '2/' + path
api2postdatatohash = path + chr(0) + post_data #new way to hash for API 2, includes path + NUL
ahmac = base64.b64encode(str(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest()))
# Create header for auth-requiring operations
header = {
"User-Agent": 'genBTC-bot',
"Rest-Key": self.key,
"Rest-Sign": ahmac
}
I'm wondering if that extra encoding is causing my header credentials to be incorrect. I think this is another Python 2 v. Python 3 problem. I don't know how the other guy got away without changing to utf-8, because the script won't run if you try to pass a string to b64encode or hmac. Do you guys see any problems with what I am doing? Is out code equivalent?
This line specifically seems to be the problem -
ahmac = base64.b64encode(str(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest()).encode('utf-8'))
To clarify, hmac.new() creates an object to which you then call digest(). Digest returns a bytes object such as
b.digest()
b'\x92b\x129\xdf\t\xbaPPZ\x00.\x96\xf8%\xaa'
Now, when you call str on this, it turns to
b'\\x92b\\x129\\xdf\\t\\xbaPPZ\\x00.\\x96\\xf8%\\xaa'
So, see what happens there? The byte indicator is now part of the string itself, which you then call encode() on.
str(b.digest()).encode("utf-8")
b"b'\\x92b\\x129\\xdf\\t\\xbaPPZ\\x00.\\x96\\xf8%\\xaa'"
To fix this, as turning bytes into a string back into bytes was unnecessary anyhow(besides problematic), I believe this will work -
ahmac = base64.b64encode(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest())
I believe you are likely to find help in a related question of mine although it deals with the WebSocket API:
Authenticated call to MtGox WebSocket API in Python 3
Also, the HTTP 403 error seems to indicate that there is something fundamentally wrong with the request. Even if you threw the wrong authentication info at the API you should have gotten an error message as a response and not a 403. My best guess is that you are using the wrong HTTP method so check if you are using the appropriate one (GET/POST).

Rails koala "error unsupported get request" after long task - calling FB graph API

After a long task (14s and can be more with more than 600 call to Facebook) my app returns a 500 internal server error with the following description:
Koala::Facebook::APIError (GraphMethodException: Unsupported get request.)
What I do is something like this:
#FBGraph = Koala::Facebook::API.new
tud = MyUsers.all
tud.each do |user|
graph = #FBGraph.get_object(user.fb_user_id)
picture = #FBGraph.get_picture(user.fb_user_id)
thisTud = MyUsers.find(user.id)
thisTud.name = graph["name"]
thisTud.url = graph["link"]
thisTud.url_pic = picture
if thisTud.save
puts "Saved!"
else
puts "Error"
end
end
I receive (on the terminal) all the "Saved!", but after retrieving the data, it does automatically the mysql operations and it fails. And the data is not saved on the DB.
As suggested in this post I have placed the #FBGraph = Koala::Facebook::API.new in a new Thread, but nothing changes.
Note: when I'd do the same operations with less users, all was working good.
How hellvinz says is a facebook bug.
I have find a workaround for now that seems that works:
change this
graph = #FBGraph.get_object(user.fb_user_id)
to this
graph = #FBGraph.get_object("#{user.fb_user_id}?fields=id,name,username,picture,link")
Explicitly declaring the fields seems that solve the problem.
And if this is not sufficient there are 2 more tricks that can resolve the problem:
Calling again after a time delay (for example after an hour), and calling only the requests incomplete
Creating multiple fb app ID and accounts differentiating the requests with the accounts

speedy_c2dm: NoMethodError (undefined method `gsub' for nil:NilClass)

I set up speedy_c2dm to send "push" messages to android devices.
The gem was working fine, but now I get this NoMethodError message when I call
SpeedyC2DM::API.send_notification(options)
the options parameter is good, I have verified this.
From the ruby-doc I got the following code from the gem:
def get_auth_token(email, password)
data = "accountType=HOSTED_OR_GOOGLE&Email=#{email}&Passwd=#{password}&service=ac2dm"
headers = { "Content-type" => "application/x-www-form-urlencoded",
"Content-length" => "#{data.length}"}
uri = URI.parse(AUTH_URL)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
response, body = http.post(uri.path, data, headers)
return body.split("\n")[2].gsub("Auth=", "")
end
You can see that the last line uses gsub, so I believe the problem is in the authentication method.
I have changed the password of the account since I created this, I updated the file with the password, initializers/speedy_c2dm.rb:
C2DM_API_EMAIL = "myemail#gmail.com"
C2DM_API_PASSWORD = "mynewpassword"
SpeedyC2DM::API.set_account(C2DM_API_EMAIL, C2DM_API_PASSWORD)
Can this be causing the error? That I changed the password even though I updated this file?
(Google doesn't let me to go back to the old password, I have to create a new one different from the old ones if I change it again)
Its the only thing I can think of since I didn't modify the gem's code.
How can I fix it? C2DM is deprecated now, but its supposed to keep working for old users. I don't want to migrate to GCM if I don't need to, everything is set up to work with C2DM
Any other ideas to fix it are welcome.
The problem was fixed after I removed the "two step verification" for logging in to my email.
This change can be made in the account configuration of gmail.