How to implement access log in rails? - ruby-on-rails

I want to implement access log in the ruby layer of my application. I want to log like this for each request.
192.168.2.20 - - [28/Jul/2006:10:27:10 -0300] "GET /cgi-bin/try/ HTTP/1.0" 200 3395
127.0.0.1 - - [28/Jul/2006:10:22:04 -0300] "GET / HTTP/1.0" 200 2216
I want to create a different file for access log only like apache access log. We can log the request in the rails logger that is easily achievable but how can we create separate log file only for access log. I am using trinidad.

Everything you need can be found in the response header and body. Add a global action to your ApplicationController with a before_ or around_ action like:
/application_controller.rb
around_filter :logging_traffic
def logging_traffic
logger.info "USERAGENT: #{request.headers['HTTP_USER_AGENT']}"
begin
yield
ensure
logger.info "response_status: #{response.status}"
end
end

Related

how to disable rails/unicorn default requests log

We have a rails app(v5.2.6) running inside a unicorn.
we are bombarded with log msgs like the following:
24.33.33.243, 12.0.52.41 - - [26/Jun/2022:13:43:39 +0000] "GET /our_path HTTP/1.1" 200 - 0.0078
No idea where this log is coming from? its bombarding our log and I must find a way to filter it.
We have a custom Rails.logger, where we also filter some msg that applies to some regexs, the problem is that this msg gets to the log from another place

Use a regex to keep the access logs with HTTP response 4** and 5**

I'm using Graylog to manage my server logs.
I would like to filter the apache logs access to keep the logs with a http response code 4** and 5**
So I would like to use a regex:
If I search /HTTP/ I have the corresponding logs like:
[...] "HEAD /register HTTP/1.1" 301 460 "-" [...]
But if I search /HTTP\//, I have no message. I also tried with /HTTP\\// but same result.
I tried with the regex /HTTP(?:.*?)"\s[4|5](?:\d{2})/ but no message found.
How to search a simple pattern like HTTP/ with a regex in Graylog ?
Thx
Why don't you use an extractor to map http-status-codes to fields.
Then you can easily filter and group your logs to find those with special codes.
Please see the following links
Extractors
How to use a JSON extractor

Ruby On Rails - Redirect entire request

I have a Rails API 4.2.10 and a NodeJS API.
Some of the Rails Request are deprecated and needs to be redirected to the NodeJS API.
I would like to not do the redirection by my WebServer (NgInx) but somewhere in Rails.
I would like to redirect the entire request => Url, Headers, body....
And return the NodeJS API body & status code.
Being a noob in ruby I tried some like making the requests myself but the Rails API still uses the create methods & so the related objects for example.
Here is my controller code :
class Api::V2::RedirectController < ActionController::API
def apiV3
redirect_to 'http://api-v3-node/api/v3' end
end
When I try with Postman, I get logs but "Could not get any response"
Here are the corresponding outputs :
[2018-09-11T13:08:12.633224 #61] INFO -- : Started POST "/api/v2/notes?token=[FILTERED]" for 172.19.0.1 at 2018-09-11 13:08:12 +0000
[2018-09-11T13:08:12.656050 #61] INFO -- : {:_method=>"POST", :_path=>"/api/v2/notes", :_format=>:json, :_controller=>"Api::V2::RedirectController", :_action=>"apiV3", :_status=>302, :_duration=>1.05, :_view=>0.0, :_location=>"http://api-v3-node/api/v3", :short_message=>"[302] POST /api/v2/notes (Api::V2::RedirectController#apiV3)"}

Upload CSV via POST in Rails

I am trying to upload a csv file to Rails and parse it into a db. I have tried using both Paw and Postman to send the http request, specifying POST, attaching the csv file, and specifying Content-Type as application/csv
The request header:
POST /skate_parks/import HTTP/1.1
Content-Type: text/csv
Host: localhost:3000
Connection: close
User-Agent: Paw/2.3.4 (Macintosh; OS X/10.11.5) GCDHTTPRequest
Content-Length: 11663
Name,Address,Suburb,Postcode,State,Business Category,LGA,Region,
Aireys Inlet Skate Park,Great Ocean Road,Aireys Inlet,3231,VIC,Skate Parks,Surf Coast,Barwon S/W, etc...
The controller skate_parks_controller.rb
def import
SkatePark.import(params[:body])
end
The model
class SkatePark < ApplicationRecord
require 'csv'
def self.import(file)
CSV.foreach("file", headers: true) do |row|
skate_park_hash = row.to_hash
skate_park = SkatePark.where(name: skate_park_hash["name"])
if skate_park.count == 1
skate_park.first.update_attributes(skate_park_hash)
else
SkatePark.create!(skate_park_hash)
end
end
end
end
The error
Started POST "/skate_parks/import" for ::1 at 2016-05-26 13:48:34 +1000
Processing by SkateParksController#import as HTML
Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.0ms)
Errno::ENOENT (No such file or directory # rb_sysopen - file):
app/models/skate_park.rb:6:in `import'
app/controllers/skate_parks_controller.rb:7:in `import'
The problem is params[:body] is nil, so you're essentially calling SkatePark.import(nil). Rails doesn't put the raw POST body into params like you've apparently assumed it does.
You have two options. The better option, in my opinion, is to upload the data as multipart/form-data. Rather than putting the raw data into the POST body, you'll do the same thing a browser does when a user chooses a file in an <input type="file">, which is to say you'll encode it as form data. When you do that, you will be able to access the data through params, as described in the Form Helpers Rails Guide under "Uploading Files." (Since you apparently aren't using a form, you can skip to "What Gets Uploaded" to see how to handle the data you receive.)
To test this with Postman, follow the instructions for "form-data" under "Request body" in the Sending Requests docs, which I'll excerpt here for posterity:
multipart/form-data is the default encoding a web form uses to transfer data. This simulates filling a form on a website, and submitting it. The form-data editor lets you set key/value pairs (using the key-value editor) for your data. You can attach files to a key as well.
Your other option is to access the POST body directly via request.raw_post as described here: How to access the raw unaltered http POST data in Rails? This is not very "Railsy," however, and among other things will be harder to test.

Rails omniauth-shopify-oauth2: "[API] Invalid API key or access token (unrecognized login or wrong password)" from console

I set up shopify auth (omniauth-shopify-oauth2 gem) for my rails 3.2.6 app.
It works fine when routed from a web page (to the following controller#action)
class ShopifyController < ApplicationController
...
def login
redirect_to "/auth/shopify?shop=#{current_retailer.primary_host_name}"
end
It redirects me to shop login and, once I am logged in, redirects back to success callback. All good (see SERVER LOG SUCCESS below).
But when I try to do pretty much the same from the rails console:
irb(main):001:0> RestClient.get 'http://localhost:3000/auth/shopify?shop=vinehillposters.myshopify.com'
I get:
RestClient::Unauthorized: 401 Unauthorized: <?xml version="1.0" encoding="UTF-8"?>
<hash>
<errors>[API] Invalid API key or access token (unrecognized login or wrong password)</errors>
</hash>
see SERVER LOG FAIL below
SERVER LOG SUCCESS:
Processing by ShopifyController#login as HTML
... AR stuff snipped ...
Redirected to http://localhost:3000/auth/shopify?shop=vinehillposters.myshopify.com
Completed 302 Found in 93ms (ActiveRecord: 1.6ms)
(shopify) Setup endpoint detected, running now.
(shopify) Request phase initiated.
"https://vinehillposters.myshopify.com/admin/oauth/authorize?response_type=code&client_id=44dd9799fbc268c36ef609f0c2386b8c&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fshopify%2Fcallba
ck&scope=read_orders"
Started GET "/auth/shopify?shop=vinehillposters.myshopify.com" for 127.0.0.1 at 2012-10-30 11:24:21 +0000
(shopify) Setup endpoint detected, running now.
(shopify) Callback phase initiated.
Started GET "/auth/shopify/callback?code=c8c6696ed347e37324d2d62ec203457b&shop=vinehillposters.myshopify.com&timestamp=1351596261&signature=e6324b041d6a6ed1e07719a8909d70f7" for 127.0.0.1 at
2012-10-30 11:24:21 +0000
Processing by ShopifyController#auth_callback as HTML
...
SERVER LOG FAILURE:
(shopify) Setup endpoint detected, running now.
(shopify) Request phase initiated.
"https://vinehillposters.myshopify.com/admin/oauth/authorize?response_type=code&client_id=44dd9799fbc268c36ef609f0c2386b8c&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fshopify%2Fcallback&scope=read_orders"
Started GET "/auth/shopify?shop=vinehillposters.myshopify.com" for 127.0.0.1 at 2012-10-30 11:24:54 +0000
You may have noticed that I print out the request_phase url right before it gets redirected to shopify (after (shopify) Request phase initiated.). It is the same in both cases. Except in one case it returns success and in another it is 401.
So, what am I doing wrong?
I think your question is confusing and you are focusing on the wrong part. What you need to do is once your user has logged in grab some information about them from the shopify callback.
def shopify
shopify_domain = params[:shop]
#your_shop_object = your_finds_or_initializes_shop_or_auth_object_with shopify_domain, token
if #your_shop_object.persisted?
redirect_to root_url
else
# something went wrong :/
session['devise.shopify_data'] = request.env['omniauth.auth']
redirect_to auth_index_url
end
end
private
def token
request.env['omniauth.auth']['credentials']['token']
end
Now with this you can use that persisted shop objects data to set up an authorized session
session = ShopifyAPI::Session.new(domain, authentication_token)
if session.valid?
ShopifyAPI::Base.activate_session(session)
# Now you can make api calls for that shop (domain)
else
Rails.logger.error "[Shop] Could not create a valid session for '#{domain}'"
end

Resources