Co to jest pingback? Jest to rodzaj notyfikacji dotyczącej umieszczenia linku do danego źródła w tekście. Notyfikację tę my możemy zarówno wysłać jak i otrzymać.

Dziś napiszę jak my możemy odebrać taki pingback i co musi zostać spełnione, zaś następnym razem opisze sposób wysyłania takiej notyfikacji.

To co będziemy potrzebować (choć nie jest to konieczne) to biblioteka XML-RPC.NET – ułatwi nam ona znacząco implementację – gdyż komunikacja odbywa się poprzez XML-RPC, oczywiście dla hardcorów istnieje opcja napisania tego samemu, ale po co?

Implementacja

By móc otrzymać pingback musimy zaimplementować metodę pingback.ping – nie jest ona jakoś trudna do implementacji, ale wymaga pewnego sprawdzania po naszej stronie.

Metoda ta przyjmuje jedynie dwa parametry:

  • URL skąd pochodzi request
  • URL jakiego zasobu u nas on tyczy

W zależności od tego czy parametry są podane czy też nie, można zwracać różne błędy opisane w specyfikacji protokołu.

Kod nie jest skomplikowany, wymaga trochę sprawdzania itp. Pominąłem kilka kwestii jak i nie dałem pełnego kodu – na przykład ExistsOn powoduje pobranie strony z netu jeżeli jest ona mniejsza niż rozmiar X i sprawdza czy nasz link istnieje tam.

using System;

namespace SomeNamespace
{
    // http://www.hixie.ch/specs/pingback/pingback
    public interface IPingbackService
    {
        [XmlRpcMethod("pingback.ping")]
        string pingback(string sourceUri, string targetUri);
    }

    public class PingbackService : XmlRpcService, IPingbackService
    {
        public PingbackService()
        {
            // we can initializers here - db etc
        }

        string IPingbackService.pingback(string sourceUri, string targetUri)
        {
            if (sourceUri.IsNullOrEmpty())
            {
                throw new XmlRpcFaultException(16, "The source URI does not exist.");
            }

            if (targetUri.IsNullOrEmpty())
            {
                throw new XmlRpcFaultException(32, "The specified target URI does not exist.");
            }

            // check if url (target) exists on page that is linking to us (we do not want to have spam comments)
            // title is read from the loaded resources from sourceUri and used as comment title
            var title = string.Empty;
            if (targetUri.ExistsOn(sourceUri, out title) == false)
            {
                throw new XmlRpcFaultException(17, "The source URI does not contain a link to the target URI, and so cannot be used as a source.");
            }

            var slug = get_slug(targetUri);

            // open db connection
            using (var session = db.Open())
            {
                var post = new Post(); // execute query to get post

                if (post == null)
                {
                    throw new XmlRpcFaultException(33, "The specified target URI cannot be used as a target. It either doesn't exist, or it is not a pingback-enabled resource.");
                }

                var comments = post.Comments;
                // check if comments are allowed
                if (comments.AreCommentsClosed()|| post.AllowComments == false)
                {
                    throw new XmlRpcFaultException(33, "The specified target URI cannot be used as a target. It either doesn't exist, or it is not a pingback-enabled resource.");
                }

                // check if comment from sourceUri already exists - we do not want to have duplicates
                var exists = comments.UrlExists(sourceUri);
                if (exists)
                {
                    throw new XmlRpcFaultException(48, "The pingback has already been registered.");
                }

                // create new comment and assign values to it
                var comment = new PostComment();
                // comment.Title = "Pingback from: {0}".FormatWith(title);
                
                // if needed check if this comment is a spam (Aksiment etc)
                
                // if everything is ok, add comment and save data
                post.Comments.Add(comment);
                // exeute save
            }

            // return some string
            return "Your ping request has been received successfully.!";
        }

        private string get_slug(string url)
        {
            var start = url.LastIndexOf("/") + 1;
            var slug = url.Substring(start).ToLowerInvariant();

            return slug;
        }
    }
}
  

Konfiguracja

Mają już kod, musimy go jakoś udostępnić, tutaj przydaje się ASP.NET Handler – ASHX/AXD. Wystarczy albo zdefiniować go w Web.Config:

<system.web>
  <httpHandlers>
    <add verb="*" path="pingback.axd" type="Namespace.PingbackService, AssemblyNam" validate="false"/>
  </httpHandlers>
</system.web>
<system.webServer>
  <handlers accessPolicy="Read, Write, Script, Execute">
    <add name="Pingback" verb="*" path="pingback.axd" type="Namespace.PingbackService, AssemblyName" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode"/>
  </handlers>
</system.webServer>

Lub po prostu dodajemy plik o nazwie PingbackService.ashx do projektu z treścią:

<%@ WebHandler="" Language="C#" Class="Namespace.PingbackService" %>

Autowykrywanie

Ostatnim krokiem jaki musimy zrobić to dodać kod do naszej strony WEB który poinformuje usługę wysyłającą, pingback o tym, że my go przyjmujemy.

Tutaj mamy kilka opcje, jedną z nich jest dodanie nagłówka do response zawierającego wartość X-Pingback z pełnym URL do serwisu/handler.

Można to osiągnąć w metodzie Application_BeginRequest w HttpApplication lub za pomocą Web.config:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    var urlHelper = new UrlHelper(Context.Request.RequestContext);
    Context.Response.AddHeader("X-Pingback", urlHelper.AbsoluteContent("~/services/pingback.ashx"));
}

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="X-Pingback" value="http://FULL_URL/pingback.ashx" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

Możemy także dodać element link do strony z rel="pingback" i href który odwołuje się do pełnego adresu URL serwisu/handler.

<link rel="pingback" href="http://FULL_URL/pingback.ashx" />

Podsumowanie

Dodanie tego nie jest trudne, jak już wiadomo o co chodzi i jak to ma działać. Mi osobiście najwięcej zajęło zrozumienie co to jest pingback i na
jakiej zasadzie on działa. Jak już to zrozumiałem to napisanie kodu było kwestią kilku minut.

Następnym razem napiszę jak wysyłać pingbacki z naszej strony, a tym czasem – jakieś uwagi? Sugestie? :)

2 KOMENTARZE

  1. dotnetomaniak wysyla trackbacki – tutaj musialem recznie poprawic bo w trackback mialem buga ;) to ze wysyla trackbacki mozna zobaczyc przy postcie z odbieraniem :)

Comments are closed.