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? :)
Sądząc po pierwszym komentarzu działa :)
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.