macOSで80番ポートを開ける

macOS 10.12.4、加えてmacOS Server (Server.app) 5.3.1を想定。


まず、普通に開けようとすると以下のようにエラーになる。

$ ruby -rwebrick -e 'WEBrick::HTTPServer.new(:DocumentRoot => "./", :Port => 80).start'
[2017-06-09 01:03:38] INFO  WEBrick 1.3.1
[2017-06-09 01:03:38] INFO  ruby 2.3.0 (2015-12-25) [x86_64-darwin15]
/Users/shuma/.anyenv/envs/rbenv/versions/2.3.0/lib/ruby/2.3.0/socket.rb:205:in `bind': Permission denied - bind(2) for 0.0.0.0:80 (Errno::EACCES)
  from /Users/shuma/.anyenv/envs/rbenv/versions/2.3.0/lib/ruby/2.3.0/socket.rb:205:in `listen'
   from /Users/shuma/.anyenv/envs/rbenv/versions/2.3.0/lib/ruby/2.3.0/socket.rb:759:in `block in tcp_server_sockets'
...

使ってるサーバは違えど、bind時にPermission denied系統が投げられる。
これはMacのセキュリティ仕様として、1000番ポート以下を一般ユーザが開けられないため。昇格すればいける。

$ sudo ruby -rwebrick -e 'WEBrick::HTTPServer.new(:DocumentRoot => "./", :Port => 80).start'
Password:
[2017-06-09 01:06:25] INFO  WEBrick 1.3.1
[2017-06-09 01:06:25] INFO  ruby 2.3.0 (2015-12-25) [x86_64-darwin15]
[2017-06-09 01:06:25] INFO  WEBrick::HTTPServer#start: pid=35327 port=80

環境によっては、以下のようになる。

$ sudo ruby -rwebrick -e 'WEBrick::HTTPServer.new(:DocumentRoot => "./", :Port => 80).start'
Password:
[2017-06-09 01:08:05] INFO  WEBrick 1.3.1
[2017-06-09 01:08:05] INFO  ruby 2.3.0 (2015-12-25) [x86_64-darwin15]
/Users/shuma/.anyenv/envs/rbenv/versions/2.3.0/lib/ruby/2.3.0/socket.rb:205:in `bind': Address already in use - bind(2) for 0.0.0.0:80 (Errno::EADDRINUSE)
  from /Users/shuma/.anyenv/envs/rbenv/versions/2.3.0/lib/ruby/2.3.0/socket.rb:205:in `listen'
   from /Users/shuma/.anyenv/envs/rbenv/versions/2.3.0/lib/ruby/2.3.0/socket.rb:759:in `block in tcp_server_sockets'
...

Address already in use、つまり80番ポートが使用されている。
Macにはapacheがビルトインされているので、ほとんどの場合こいつのせい。以下で自動起動を辞めさせられる。

$ sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist

ただし、macOS Server (Server.app) の場合は

$ sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist
/System/Library/LaunchDaemons/org.apache.httpd.plist: Could not find specified service

なんて風になって止められない。80番ポートを自由に使いたいという前提で進めているので、apacheの80番ポートlistenを辞めさせればいい。
/Library/Server/Web/Config/apache2/httpd_server_app.confにある設定ファイルで、以下のようにコメントアウト。

#Listen 80
#Listen 443

内部では80番ポートが見えるが、外からは永遠に待たされるなど見えない場合がある。
nmapなんかで確認すると

$ nmap 127.0.0.1

Starting Nmap 7.12 ( https://nmap.org ) at 2017-06-09 01:23 JST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00074s latency).
Not shown: 722 closed ports, 268 filtered ports
PORT     STATE SERVICE
80/tcp   filtered  http
...

なんて風になっているかもしれない。これはMacのファイアウォールで許可していないため。
環境設定からファイアウォールのオプションを開き、接続許可をすれば良い。

f:id:S64:20170609012734p:plain

android-radiobutton-extendedを公開しました。

AndroidのRadioButtonを拡張するコンポーネント郡をOSSとして公開しました。

github.com

以下のコンポーネントが含まれます:

  • CompoundFrameLayout
  • RadioFrameLayout
  • RadioGroupedAdapter

CompoundFrameLayout, RadioFrameLayout

CheckableなFrameLayoutの実装です。
選択中 / 選択解除の表現が必要なレイアウトで利用するのがおすすめです。
たとえば、backgroundとしてandroid:state_checkedで表示が切り替わるdrawableを作るとよいでしょう。

RadioGroupedAdapter

RecyclerViewで単一チェックのみを許容するAdapterを表現するサンプル実装です。RadioGroupに似た挙動をするAdapterだとイメージしてください。
実体はRadioGroupedAdapter.Helperになっているため、既存のカスタムAdapterがある場合、内部のフィールドで呼び出すと上手く使えます。

Example

それぞれexampleというモジュール内にサンプル実装が存在します。
なお、exampleはPlay Store上でデモアプリを公開しています。

play.google.com

License

Apache License 2.0です。

今後の予定

  • 0.1.0なので、破壊的変更をするかも
  • 趣味ではXamarinをよくやるので、Bindingを作りたい