Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

機能追加(4/4): 短縮URLの展開機能を追加 #223

Merged
merged 1 commit into from
Nov 27, 2016

Conversation

awazi
Copy link

@awazi awazi commented Nov 18, 2016

短縮URLの展開機能の追加です。
対象となるサイトは、t.coを除きヘッダのリクエストでLocation:が返ってくるものを対象にしています。
($ curl -I -i URL (linuxの場合) にて確認)
ただし、youtu.beのようなサムネイルの取得で対応可能と思われるものは含まれていません。

よろしくお願いします。

@eru
Copy link
Member

eru commented Nov 20, 2016

😻

xhr = new XMLHttpRequest()
if /// //t\.co/ ///.test(targetUrl)
xhr.open("GET", targetUrl)
xhr.responseType = "document"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t.coの場合でも、HEADリクエストでlocation取得できるようですが、敢えて分けている理由を教えてください。

$ curl --head -I https://t.co/9fGZDZz3P2
HTTP/1.1 301 Moved Permanently
cache-control: private,max-age=300
content-length: 0
date: Sun, 20 Nov 2016 02:26:54 GMT
expires: Sun, 20 Nov 2016 02:31:54 GMT
location: https://readcrx-2.github.io/read.crx-2/
server: tsa_m
set-cookie: muc=63353035-57cf-4443-b3de-4f8f7cfc891a; Expires=Fri, 02 Nov 2018 02:26:54 UTC; Domain=t.co
strict-transport-security: max-age=0
x-connection-hash: 4cc500c45ecc8f6263fe0a890c43d822
x-response-time: 102

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確認します。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

もしHEADだけになるならapp.HTMLを利用してください

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t.coの例外処理についてですが、XMLHttpRequest()でHEADリクエストをした場合は、何故かstatus=200でrespons headにlocationがありません。詳しい理由がわからないのでGETリクエストを使用しています。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

リクエスト時のUserAgentヘッダーを消すと301が戻ってきました

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

情報ありがとうございます。
curlコマンドとのヘッダーの違いはUser-AgentとCookieくらいだったので、実験して試そうと思っていました。

asyncProcessDfds = []

# 短縮URLの展開と追加
expandShortURL = (aSrc, targetUrl) ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

基本的には、スレッドの表示以外では使う機会がなさそうですが、
短縮URLの展開機能として独立させて、core/URL.tsか、core/util.coffeeへ移動したほうがいいと思います。

@S--Minecraft ↑どう(どっちがいい)でしょう?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そうですね
core/URL.tsがいいかなと

checkShortURL = (tUrl) ->
if tmp = /// ^h?ttps?://([\w\-\.]+)/.+ ///.exec(tUrl)
return true if shortUrlSites.indexOf(tmp[1]) >= 0
return false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可読性が若干損なわれますが、速度優先で正規表現判定一発にしちゃいましょう。
core/URL.ts に移動をお願いします。

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

了解しました。

expandedURL.setAttribute("short-url", sourceA.href)

if finalUrl is ""
expandedURL.appendChild(document.createTextNode("展開できませんでした。"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

クラスを追加してcssで::afterをつけるほうがよいのでは?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

やってみます。

expandedURL.appendChild(document.createTextNode("展開できませんでした。"))
else
expandedURLLink = document.createElement("a")
expandedURLLink.appendChild(document.createTextNode(finalUrl))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expandedURLLink.textContent = finalUrl

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

はい。

xhr = new XMLHttpRequest()
if /// //t\.co/ ///.test(targetUrl)
xhr.open("GET", targetUrl)
xhr.responseType = "document"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

もしHEADだけになるならapp.HTMLを利用してください

)
else
return d.resolve()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

app.util.concurrentではだめですか?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

既存の方法ですっきりさせたいのですが、短縮URLの展開後のサムネイルの確認などがあり、それぞれの終了時の処理内容など、うまい方法がないか検討中です。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkUrl = (a) ->
  d = new $.Deffered()
  if app.config.get("expand_short_url") isnt "none"
    if app.url.checkShortURL(a.href)
      app.url.expandShortURL(a, a.href).done( (a, finalUrl) ->
        newLink = addExpandedURL(a, finalUrl)
        if finalUrl
          d.resolve(a, newLink)
        else
          d.resolve(a, a.href)
        return
      )
    else
      d.resolve(a, a.href)
  else
    d.resolve(a, a.href)
  return d.promise()
  
app.util.concurrent(@container.querySelectorAll(".message > a:not(.thumbnail):not(.has_thumbnail)"), (a) ->
  checkUrl(a).done( (a, link) ->
    return app.ImageReplaceDat.do(a, link)
  ).done( (a, res, err) ->
    # addThumbnail関連
  )
)

これでどうでしょう?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

提案ありがとうございます。
非同期プログラミングに不慣れな身としては何がなんだか。と言った感じですが試してみます。

%br
%label
タイムアウト:
%input.direct(type="number" name="expand_short_url_timeout" min="0" max="5000")ms
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

設定につくらずに固定値でいいのでは?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

元々は特にタイムアウトは指定していなかったのですが、時々異常に時間のかかるものがあることからタイムアウトの必要性を感じ追加しました。
正常に終了するまでの時間のばらつきが大きく、適正と思われる値を固定化するのが難しいと感じ設定可能としました。

@awazi
Copy link
Author

awazi commented Nov 23, 2016

修正しました。

変更箇所
・checkShortURL()とexpandShortURL()をcore/URL.tsに移動
・短縮URLのチェックを正規表現で行うように変更
・XMLHttpRequestを直接呼び出さずにapp.HTTPを使用するように変更
・t.coに対する例外を廃止
・view/index.coffee内にRequestHeaderの監視を追加
・展開に失敗した場合のメッセージをCSSで表示するように変更
・タイムアウトの初期値を変更、及び上限の廃止
・app.HTTPにresponseURLを追加
・1行に複数の短縮URLが存在する場合に展開済みURLの追加順が保証されないため、短縮URLを併記するように変更

補足
・view/index.coffeeにリクエスト・ヘッダーの監視を追加しましたが、他の処理でも使用する可能性を考慮し、<all_urls>にしてあります。問題があれば変更します。
・app.HTTPにresponseURLを追加しましたが、コンパイラがresponseURLを認識しないため代用変数を使用しています。他に方法があれば修正します。
・core/URL.tsに新たに追加した関数をapp.URL.hoge()として呼び出すと実行時エラーが発生するため、app.url.hoge()として呼び出しをしています。
・app.util.concurrentを使用する方法については、サムネイルの追加と短縮URLの展開のどちらかを呼び出すようにすれば大丈夫な気もしますが、展開後のURLについてのサムネイルの追加を考えると難しい気がします。
仮にapp.util.concurrentをクラス化するなどして、処理対象となる配列要素または監視対象となるDefferedオブジェクトを後から追加可能とすればいけそうな気もしますが、追加前に処理が終了してしまった場合に全ての処理が終了したことを保証できなくなってしまいます。何か良いアイデアはありますか?

"t\.co|tiny\.cc|tinyurl\.com|tl\.gd|tr\.im|trib\.al|" +
"url\.ie|urx\.nu|urx2\.nu|urx3\.nu|ur0\.pw|" +
"wk\.tk|xrl\.us" +
")\/.+");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これだと毎回正規表現コンパイルされるので、constとしてSHORT_URL_REG = /.../としてください。
57-63行目の様な形で。

あと、.testしか使わないのであれば、関数化せずにそのままtestでもいいかと。

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

処理効率を優先すれば定数化するのは良い選択だと思いますが、設定画面からの追加・変更の可能性は閉ざされます。よろしいですか?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t.coみたいに特殊な例もあるので、短縮URLは定数でいいと思います。
追加要望あれば都度変更でも対応可能ですし(少なくとも一般的によく使われる短縮URLサービス程度であれば)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

了解しました。


resonseHeaders = Request.parseHTTPHeader(xhr.getAllResponseHeaders());

callback(new Response(xhr.status, resonseHeaders, xhr.responseText));
callback(new Response(xhr.status, resonseHeaders, xhr.responseText, xhr2.responseURL));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typescriptのバグっぽいですね microsoft/TypeScript#11510
2.1.3で修正されるみたいなのでとりあえずのところ
一行目に///<reference path="../global.d.ts" />と書いて
global.d.tsに以下の記述をするとコンパイルを通せると思います

namespace XMLHttpRequest {
  declare var responseURL: string;
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上記の修正をしましたが、以下のエラーが発生します。

src/global.d.ts(7,11): error TS2300: Duplicate identifier 'XMLHttpRequest'.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あ、namespaceじゃなくてinterfaceでした
すいません…


return {requestHeaders: details.requestHeaders}
,{
urls: ["<all_urls>"],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

追加するときに追加すればよいのでは…?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

では現状ではt.coのみにします。

return

# 短縮URLの展開でのt.coに対する例外
if details.method is "HEAD" and /// //t\.co/ ///.test(details.url)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

app.URL.getDomain(details.url) is "t.co"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

了解しました。

)
).always(=>
d.resolve()
# Audioの確認
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

元々Audio/VideoがImageReplaceDatの処理後だったのがそうでなくなってます
おそらく817行目のあとにくるべきかと

)
else
return d.resolve()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkUrl = (a) ->
  d = new $.Deffered()
  if app.config.get("expand_short_url") isnt "none"
    if app.url.checkShortURL(a.href)
      app.url.expandShortURL(a, a.href).done( (a, finalUrl) ->
        newLink = addExpandedURL(a, finalUrl)
        if finalUrl
          d.resolve(a, newLink)
        else
          d.resolve(a, a.href)
        return
      )
    else
      d.resolve(a, a.href)
  else
    d.resolve(a, a.href)
  return d.promise()
  
app.util.concurrent(@container.querySelectorAll(".message > a:not(.thumbnail):not(.has_thumbnail)"), (a) ->
  checkUrl(a).done( (a, link) ->
    return app.ImageReplaceDat.do(a, link)
  ).done( (a, res, err) ->
    # addThumbnail関連
  )
)

これでどうでしょう?

@awazi
Copy link
Author

awazi commented Nov 24, 2016

指摘のあった箇所を修正しました。
ただし、core/HTTP.tsについては別のエラーが発生するため変更していません。
また、提案していただいたapp.util.concurrentの処理については一部修正をしました。

Copy link
Member

@S--Minecraft S--Minecraft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

app.util.concurrentの件一応テストだけお願いします(パパっと書いたものなので…)


resonseHeaders = Request.parseHTTPHeader(xhr.getAllResponseHeaders());

callback(new Response(xhr.status, resonseHeaders, xhr.responseText));
callback(new Response(xhr.status, resonseHeaders, xhr.responseText, xhr2.responseURL));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あ、namespaceじゃなくてinterfaceでした
すいません…

@awazi
Copy link
Author

awazi commented Nov 24, 2016

コンパイル出来るようになりました。ありがとうございます。
app.util.concurrentについては、動作確認をした際に判明した不具合を修正しています。

checkUrl(a).done( (a, link) ->
return app.ImageReplaceDat.do(a, link).done( (a, res, err) ->
# サムネイルの追加
addThumbnail(a, res.text, "image", res.referrer, res.cookie) unless err?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unless err?はaudio,videoの処理にもかけないといけないのでは?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

audioとvideoは、ImageViewURLReplace.datに依存しなため不要と考えます。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ImageViewURLReplace.datでurlをaudio/videoのmp4などへのurlに置き換えることもあるのでは?

".message > a:not(.thumbnail):not(.has_thumbnail):not(.expandedURL):not(.has_expandedURL)"
), (a) ->
checkUrl(a).done( (a, link) ->
return app.ImageReplaceDat.do(a, link).done( (a, res, err) ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkUrl(a).done( (a, link) ->
  return app.ImageReplaceDat(a,link)
).done( (a,res,err) ->
  〜
)

よくかんがえたらこうかけました
インデント減るのでこっちで…

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

元々そのように書かれていましたが、サムネイルが表示されないため修正しました。
(aは受け取れてもresを受け取れないため?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

すいませんちょっといろんな仕様を混同してました
doneを両方ともthenにするといけるはずです

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thenに変更して動くようになりました。

@awazi
Copy link
Author

awazi commented Nov 25, 2016

変更箇所
app.util.concurrent周りの処理
app.ImageReplaceDatでのaudio/videoへの置き換えに対応 (これにより、oggファイルの設定をaudio/videoの両方に設定されていた場合はaudioとみなされます。また、audio/videoの使用設定をせずに置き換えが行われた場合はimageとして扱われるため正しく表示されません)

@awazi
Copy link
Author

awazi commented Nov 26, 2016

変更箇所
・audio/videoの使用設定をせずにImageViewURLRepace.datでの置き換えが行われた場合は無視するように変更 (oggファイルの設定をaudio/videoの両方に設定されていた場合はvideoとみなされます)

Copy link
Member

@eru eru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@eru eru merged commit bac17b7 into readcrx-2:develop Nov 27, 2016
@awazi awazi deleted the dev3-4 branch December 15, 2016 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants