3

I have a relatively standard web application built with Sinatra. The application is running in Ruby 2.7.0 on Mac OS Catalina.

In one of the routes data is passed to the method get_activity_status. The method takes two arguments: name and status_id.

I have the following output from Pry:

From: /Users/nathanielsuchy/Code/activitypub/utils/get_activity_status.rb @ line 4 Object#get_activity_status:

    1: require "pry"
    2: # Generate ActivityPub/Activity Streams Status
    3: def get_activity_status(name, status_id)
 => 4:     binding.pry
    5:     tweet = get_twitter_status("https://twitter.com/#{name}/status/#{status_id}")
    6:     return {
    7:       "@context": [
    8:         "https://www.w3.org/ns/activitystreams",
    9:           {

[1] pry(#<Sinatra::Application>)> pp name
"glaad"
=> "glaad"
[2] pry(#<Sinatra::Application>)> pp status_id
"outbox"
=> "outbox"
[3] pry(#<Sinatra::Application>)> 

The main application is like this, with non-related routes removed:

require 'sinatra'
require 'sqlite3'
require 'http'
require 'json'
require 'openssl'
require 'nokogiri'
require 'httparty'

# Include classes
require './classes/profile.rb'
require './classes/tweet.rb'

# Include utils
require './utils/get_twitter_status.rb'
require './utils/get_twitter_profile.rb'
require './utils/get_activity_status.rb'
require './utils/get_activity_profile.rb'

# Configure URLs
BASE_URL = "http://localhost:4567" # URL should be protocol://hostname:port WITHOUT THE TRAILING SLASH
HOSTNAME = BASE_URL
            .gsub("http://", "")
            .gsub("https://", "")
            .gsub(":4567", "")

# Configure bind and port
set :bind, '0.0.0.0'
set :port, 8000
set :public_folder, File.dirname(__FILE__) + '/static'

# Configure OpenSSL
PUBLIC_KEY = File.read("./keys/public_formatted.pem")
PRIVATE_KEY = OpenSSL::PKey::RSA.new(File.read('./keys/private.pem'))

# Configure SQLite3 Database
$db = SQLite3::Database.new "database.sqlite3" # You can rename this database if you want.

# Configure routes

...

# ActivityPub Profile Outbox
get '/:name/outbox' do
  headers = {
    "Content-Type" => "application/activity+json"
  }

  body = {
    "Id": "#{BASE_URL}/#{params['name']}/outbox",
    "Type": "OrderedCollection",
    "TotalItems": "1",
    "OrderedItems": [
      {
        "Id":     "#{BASE_URL}/#{params['name']}/status/1210253456252055552",
            "Type":   "Create",
            "Actor":  "#{BASE_URL}/#{params['name']}/status/1210253456252055552",
            "To":     ["https://www.w3.org/ns/activitystreams#Public"],
            "Cc":     ["#{BASE_URL}/users/#{params['name']}/followers"],
            "Object": get_activity_status("glaad", "1210253456252055552")
      }
    ] 
  }

  return [200, headers, body]
end

Somehow app.rb is changing the value of status_id before it's passed to get_activity_status. Why is this occurring?

If a closer look at the application is required it can be found on GitHub https://github.com/nsuchy/TwitterPub

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • 1
    FYI: Don't use `gsub` like you are when massaging the `BASE_URL`, at least use `sub` or slice the string. `gsub` is slower, and is wasting CPU. In this particular instance it's not going to make much difference, but it's not a good habit. It's about using the right tools in the toolbox and Ruby comes with [URI](https://ruby-doc.org/stdlib-2.7.0/libdoc/uri/rdoc/index.html), which is actually the right tool, in particular the [`hostname`](https://ruby-doc.org/stdlib-2.7.0/libdoc/uri/rdoc/URI/Generic.html#method-i-hostname) method. `HOSTNAME = URI(BASE_URL).hostname # => "localhost"` – the Tin Man Jan 07 '20 at 19:33
  • 1
    I'd also recommend reading https://stackoverflow.com/q/3672586/128421. – the Tin Man Jan 07 '20 at 19:43

1 Answers1

3

Somehow app.rb is changing the value of status_id before it's passed to get_activity_status. Why is this occurring?

It doesn't. When you hit /:name/outbox in fact this block is called https://github.com/nsuchy/TwitterPub/blob/master/app.rb#L152, not the last one as you might expect. It happens because /:name/:status_id matches the /:name/outbox too (in this case status_id is resolved to outbox). Just reorder the routes' definitions (put the static above the dynamic one) and it should work...

Konstantin Strukov
  • 2,899
  • 1
  • 10
  • 14