diff --git a/app/controllers/diaspora_federation/webfinger_controller.rb b/app/controllers/diaspora_federation/webfinger_controller.rb
index 0e755cd..0521ed9 100644
--- a/app/controllers/diaspora_federation/webfinger_controller.rb
+++ b/app/controllers/diaspora_federation/webfinger_controller.rb
@@ -16,6 +16,81 @@ module DiasporaFederation
render xml: WebfingerController.host_meta_xml, content_type: "application/xrd+xml"
end
+ # Returns the webfinger as RFC 7033 JRD or XRD.
+ #
+ # JSON example:
+ # {
+ # "subject": "acct:alice@localhost:3000",
+ # "aliases": [
+ # "http://localhost:3000/people/c8e87290f6a20132963908fbffceb188"
+ # ],
+ # "links": [
+ # {
+ # "rel": "http://microformats.org/profile/hcard",
+ # "type": "text/html",
+ # "href": "http://localhost:3000/hcard/users/c8e87290f6a20132963908fbffceb188"
+ # },
+ # {
+ # "rel": "http://joindiaspora.com/seed_location",
+ # "type": "text/html",
+ # "href": "http://localhost:3000/"
+ # },
+ # {
+ # "rel": "http://webfinger.net/rel/profile-page",
+ # "type": "text/html",
+ # "href": "http://localhost:3000/u/alice"
+ # },
+ # {
+ # "rel": "http://schemas.google.com/g/2010#updates-from",
+ # "type": "application/atom+xml",
+ # "href": "http://localhost:3000/public/alice.atom"
+ # },
+ # {
+ # "rel": "salmon",
+ # "href": "http://localhost:3000/receive/users/c8e87290f6a20132963908fbffceb188"
+ # },
+ # {
+ # "rel": "http://ostatus.org/schema/1.0/subscribe",
+ # "template": "http://localhost:3000/people?q={uri}"
+ # }
+ # ]
+ # }
+ #
+ # XML example:
+ #
+ #
+ # acct:alice@localhost:3000
+ # http://localhost:3000/people/c8e87290f6a20132963908fbffceb188
+ #
+ #
+ #
+ #
+ #
+ #
+ #
+ # GET /.well-known/webfinger?resource=
+ def webfinger
+ person_wf = find_person_webfinger(params.require(:resource))
+
+ if person_wf.nil?
+ head :not_found
+ else
+ logger.info "webfinger profile request for: #{person_wf.acct_uri}"
+
+ respond_to do |format|
+ format.any(:jrd, :json, :html) do
+ headers["Access-Control-Allow-Origin"] = "*"
+ render json: JSON.pretty_generate(person_wf.to_json), content_type: "application/jrd+json"
+ end
+ format.any(:xrd, :xml) do
+ render xml: person_wf.to_xml, content_type: "application/xrd+xml"
+ end
+ end
+ end
+ end
+
# @deprecated This is the pre RFC 7033 webfinger.
#
# example:
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
new file mode 100644
index 0000000..10cadb2
--- /dev/null
+++ b/config/initializers/mime_types.rb
@@ -0,0 +1,3 @@
+# mime types for webfinger
+Mime::Type.register "application/jrd+json", :jrd
+Mime::Type.register "application/xrd+xml", :xrd
diff --git a/config/routes.rb b/config/routes.rb
index cffd505..d6d0829 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -10,6 +10,7 @@ DiasporaFederation::Engine.routes.draw do
controller :webfinger do
get ".well-known/host-meta" => :host_meta, :as => "host_meta"
+ get ".well-known/webfinger" => :webfinger, :as => "webfinger"
get "webfinger" => :legacy_webfinger, :as => "legacy_webfinger"
end
diff --git a/spec/controllers/diaspora_federation/webfinger_controller_spec.rb b/spec/controllers/diaspora_federation/webfinger_controller_spec.rb
index e26ceeb..d740656 100644
--- a/spec/controllers/diaspora_federation/webfinger_controller_spec.rb
+++ b/spec/controllers/diaspora_federation/webfinger_controller_spec.rb
@@ -35,6 +35,91 @@ module DiasporaFederation
end
end
+ describe "GET #webfinger", rails: 5 do
+ it "uses the JRD format as default" do
+ get :webfinger, params: {resource: alice.diaspora_id}
+ expect(response).to be_success
+ expect(response.header["Content-Type"]).to include "application/jrd+json"
+ end
+
+ context "json", exceptions: :catch do
+ it "succeeds when the person exists" do
+ get :webfinger, format: :json, params: {resource: alice.diaspora_id}
+ expect(response).to be_success
+ end
+
+ it "succeeds with 'acct:' in the query when the person exists" do
+ get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
+ expect(response).to be_success
+ end
+
+ it "contains the diaspora* ID" do
+ get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
+ expect(response.body).to include "\"subject\": \"acct:alice@localhost:3000\""
+ end
+
+ it "returns a application/jrd+json" do
+ get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
+ expect(response.header["Content-Type"]).to include "application/jrd+json"
+ end
+
+ it "adds a Access-Control-Allow-Origin header" do
+ get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
+ expect(response.header["Access-Control-Allow-Origin"]).to eq("*")
+ end
+
+ it "404s when the person does not exist" do
+ get :webfinger, format: :json, params: {resource: "me@mydiaspora.pod.com"}
+ expect(response).to be_not_found
+ end
+
+ it "raises when the resource parameter is missing" do
+ expect {
+ get :webfinger, format: :json
+ }.to raise_error ActionController::ParameterMissing, "param is missing or the value is empty: resource"
+ end
+
+ it "calls the fetch_person_for_webfinger callback" do
+ expect_callback(:fetch_person_for_webfinger, "alice@localhost:3000").and_call_original
+
+ get :webfinger, format: :json, params: {resource: "acct:alice@localhost:3000"}
+ end
+ end
+
+ context "xml" do
+ it "succeeds when the person exists" do
+ get :webfinger, format: :json, params: {resource: alice.diaspora_id}
+ expect(response).to be_success
+ end
+
+ it "succeeds with 'acct:' in the query when the person exists" do
+ get :webfinger, format: :xml, params: {resource: "acct:#{alice.diaspora_id}"}
+ expect(response).to be_success
+ end
+
+ it "contains the diaspora* ID" do
+ get :webfinger, format: :xml, params: {resource: "acct:#{alice.diaspora_id}"}
+ expect(response.body).to include "acct:alice@localhost:3000"
+ end
+
+ it "returns a application/xrd+xml" do
+ get :webfinger, format: :xml, params: {resource: "acct:#{alice.diaspora_id}"}
+ expect(response.header["Content-Type"]).to include "application/xrd+xml"
+ end
+
+ it "404s when the person does not exist" do
+ get :webfinger, format: :xml, params: {resource: "me@mydiaspora.pod.com"}
+ expect(response).to be_not_found
+ end
+
+ it "calls the fetch_person_for_webfinger callback" do
+ expect_callback(:fetch_person_for_webfinger, "alice@localhost:3000").and_call_original
+
+ get :webfinger, format: :xml, params: {resource: "acct:alice@localhost:3000"}
+ end
+ end
+ end
+
describe "GET #legacy_webfinger", rails: 5 do
it "succeeds when the person exists" do
get :legacy_webfinger, params: {q: alice.diaspora_id}
diff --git a/spec/routing/webfinger_routing_spec.rb b/spec/routing/webfinger_routing_spec.rb
index be2f48c..ccb48d9 100644
--- a/spec/routing/webfinger_routing_spec.rb
+++ b/spec/routing/webfinger_routing_spec.rb
@@ -9,6 +9,13 @@ module DiasporaFederation
)
end
+ it "routes GET webfinger" do
+ expect(get: "/.well-known/webfinger").to route_to(
+ controller: "diaspora_federation/webfinger",
+ action: "webfinger"
+ )
+ end
+
it "routes GET legacy webfinger" do
expect(get: "/webfinger").to route_to(
controller: "diaspora_federation/webfinger",