playframework akka-http-server : warning Illegal header issue

Programming 2017.07.19 18:16

play 2.5->2.6으로 업그래이드 도중 만나게된 이슈 정리.


Playframework 2.6 부터는 akka-http-server를 기본 back-end 서버로 사용하도록 셋팅되어있다.


 [warn] a.a.ActorSystemImpl - Illegal header: Illegal 'accept-language' header: Invalid input '_', expected weight, OWS, 'EOI', listSep, ALPHA or '-' (line 1, column 3): zh_CN

  ^


만약 이러한 워닝을 만나게 된다면.


이유 : 

http://www.rfc-editor.org/errata_search.php?rfc=7230 규약에 위배 되는 사항들은 warn level로 경고를 날리게 되어있음.

그중 하나가 header에는 언더바(_) 문자가 들어갈 수 없다는 규약에 걸렸기 때문.


해결책 :


가장 좋은 방법은 잘못된 헤더를 안받으면 되는데, 웹서버를 nginx를 쓴다면 기본적으로 nginx가 잘못된 헤더를 걸러버리기 때문에 만나기 힘든 이슈.

그러나 나는 nginx의 header filter옵션을 꺼뒀기에 akka-http-server에서 만나게 됨.


위 warning을 끄는 방법은 


reference.conf 파일에 보면

# Enables/disables the logging of warning messages in case an incoming
# message (request or response) contains an HTTP header which cannot be
# parsed into its high-level model class due to incompatible syntax.
# Note that, independently of this settings, akka-http will accept messages
# with such headers as long as the message as a whole would still be legal
# under the HTTP specification even without this header.
# If a header cannot be parsed into a high-level model instance it will be
# provided as a `RawHeader`.
# If logging is enabled it is performed with the configured
# `error-logging-verbosity`. illegal-header-warnings = on


요런 설정이 있음.

위 설정을 off 시키면 됨.


이걸 playframework의 application.conf에 적용하면..


akka.http.parsing.illegal-header-warnings = off


sbt run으로 그냥 띄우면 적용되지 않음.

Dev 모드에서는 적용하지 않는다고 되어있음.


참고 : https://www.playframework.com/documentation/2.6.x/SettingsAkkaHttp


Note: In dev mode, when you use the run command, your application.confsettings will not be picked up by the server. This is because in dev mode the server starts before the application classpath is available. There are several other optionsyou’ll need to use instead.


저작자 표시 비영리 변경 금지
신고

[돌사진 후기] 파주 헤이리 꿈꾸는 스튜디오

분류없음 2016.10.24 22:03

어느덧 연희가 커서 돌사진 찍을 때가 왔다.

연희가 돌사진 찍는 시기가 딱 단풍이 이쁘게 들 시기라서 왠만해서는 야외에서 찍고 싶은 생각이 컸다.

그러다보니 왠지 헤이리 마을에 스튜디오가 있지 않을까? 해서 검색해본결과..

역시나 있었다.

헤이리에는 두개의 스튜디오가 있었는데 여러모로 살펴본바 마지막으로 꿈꾸는 스튜디오를 선택하게 되었다.


가격은 일반 서울/경기에 위치한 스튜디오에 비해서는 비싼 편에 속했다. 하지만 나도 사진을 좀 좋아라 하는 입장에서 싼가격에 사진을 찍어서 '잘' 찍어주는 곳을 한번도 찾아보지 못했었기에

연희 100일사진도 그냥 내가 셀프로 찍었는데 이번은 생일 선물이라고 큰맘먹고 그냥 '퀄리티' 위주로 스튜디오를 골랐다.


그렇게 예약한 꿈꾸는 스튜디오.


촬영일 경기도는 바람도 불고 꽤나 쌀쌀한 편이었다.

스튜디오에 도착했을 때 느낌은 '아늑하다'였다.


여러가지 안내를 받고 화보B를 골랐다. 역시나 가장 비싼 상품이긴하다.

그렇게 상품을 고르고 사진을 찍는데 찍으시는 작가님도 재미있었지만 옆에서 도와주시는분이 정말 정말 열성적으로 아기를 웃겨주기 시작했다.

속으로 저러다 목쉬는건 아닐까? 하는 걱정도 들었다.

바깥 날씨는 이상하게도 바람도 잘 안불고 따뜻했다. 아니 난 오히려 넘 더울정도였다.

야외 촬영도 성공적으로 마치고 


그렇게 찍은 결과물.


Canon EOS 5D Mark III | Manual | 1/500sec | F/1.4 | 50.0mm | ISO-800

Canon EOS 5D Mark III | Manual | 1/200sec | F/1.4 | 50.0mm | ISO-640

Canon EOS 5D Mark III | Manual | 1/1600sec | F/2.5 | 50.0mm | ISO-500

Canon EOS 5D Mark III | Manual | 1/1250sec | F/2.0 | 50.0mm | ISO-250

Canon EOS 5D Mark III | Manual | 1/2000sec | F/1.4 | 50.0mm | ISO-250

Canon EOS 5D Mark III | Manual | 1/800sec | F/1.4 | 50.0mm | ISO-400



역시나 내 선택은 옳았다.

거의 대부분의 사진이 다 너무 이쁘고 좋게 나와서 이건뭐.. 셀렉하는데 너무 힘들었다.

다 좋은데 어떻하지? 다 넣고싶은데!!!!

그나마 좀 비싼상품이었어서 70장을 고를 수 있어서 많이 넣었는데..

그럼에도 못들어갔으나 넘 잘나온 사진이 많았다.


만약 둘째가 생긴다면 또다시 이곳을 선택하지 싶다.


어차피 경기도에서 서울로 찍으러 가려고 해도 1시간이고 여기서 고속도로 타서 헤이리 가도 1시간이니 거리상으로도 크게 부담되지 않았다.


이번 아기 사진 촬영은 만족도 100%다.



카카오톡 친구추가 -> http://plus.kakao.com/home/@%EA%BF%88%EA%BE%B8%EB%8A%94%ED%95%98%EB%A3%A8



홈페이지 -> http://dreamingst.com



#파주일산아기사진 #베이비스튜디오 #돌사진 #야외사진 #헤이리 

저작자 표시 비영리 변경 금지
신고

판교 더 퍼스트클래스 답사후기.

분류없음 2016.06.20 22:45

우리 아기 돌잔치를 하게 된 더퍼스트클래스 판교점!



시식을 할 수 있어서 시식을 다녀왔다.


일단 파티장 곳곳의 사진!

(출처:더퍼스트클래스 카페)


맘에 들었던것은 돌잔치 전에 스냅을 찍기 좋은 채광과 좋은 인테리어였다.


적어도 돌잔치 스냅은 잘 나올수 있을것 같다.


직원분들은 무척 친절했고 시설도 깔끔하고 넓고 좋았다.


50명 기본에 90석까지 준비되어있었다.


다른 곳들처럼 50명 일지 80명일지 꼭 정하지 않아도 되어서 좋았다. 그냥 기본 50명에 혹시 많이 올경우 미리 알려만 주면 되었으니.


시식은... 좀 솔직히 적겠다.


여름에 먹어서 그런지는 모르겠으나. 그리고 내가 바닷가에서 자라서 너무 신선한 회만 먹어와서 그런지 모르겠으나 회는 완전 별로였다.

푸석푸석하고 신선함이 없었다.


하지만 스테이크는 회의 맛없음을 완전히 회복해줬다.

스테이크는 먹기 좋게 딱 적절히 굽혀졌고 고기도 좋은 고기를 쓰는것 같았다.


나머지 음식들은 평범한 뷔페식 음식이었다.

iPhone 6 | Normal program | 1/30sec | F/2.2 | 4.2mm | ISO-50

iPhone 6 | Normal program | 1/30sec | F/2.2 | 4.2mm | ISO-32

iPhone 6 | Normal program | 1/30sec | F/2.2 | 4.2mm | ISO-32

iPhone 6 | Normal program | 1/30sec | F/2.2 | 4.2mm | ISO-50

iPhone 6 | Normal program | 1/40sec | F/2.2 | 4.2mm | ISO-32

iPhone 6 | Normal program | 1/30sec | F/2.2 | 4.2mm | ISO-50

iPhone 6 | Normal program | 1/60sec | F/2.2 | 4.2mm | ISO-40

iPhone 6 | Normal program | 1/30sec | F/2.2 | 4.2mm | ISO-40

iPhone 6 | Normal program | 1/30sec | F/2.2 | 4.2mm | ISO-32

iPhone 6 | Normal program | 1/40sec | F/2.2 | 4.2mm | ISO-32


아무튼 우리 아기가 벌써 돌잔치를 할 날이 다가왔다니.. 믿기지 않는다..

저작자 표시 비영리 변경 금지
신고
이 장소를 Daum지도에서 확인해보세요.
경기 성남시 분당구 삼평동 660 골드타워 10층 | 더퍼스트클래스 파티하우스 분당판교점
도움말 Daum 지도

[scala] String으로 Class method 호출하기. ruby의 send처럼..

Programming/scala 2016.03.23 23:53

스트링 문자를 통해서 해당 문자에 해당하는 클래스를 호출해보자.


나도 잘 모르기때문에 역시나 구글사마의 도움을 받아.. 스택오버플로우를 뒤지기 시작했다.

http://stackoverflow.com/questions/2060395/is-there-any-scala-feature-that-allows-you-to-call-a-method-whose-name-is-stored


2가지 방식으로 호출이 가능한데..

자바의 refliction기법으로 한다면 아래와 같다.


class A {
  def cat(s1: String, s2: String) = s1 + " " + s2
}
val a = new A
val hi = "Hello"
val all = "World"
val method = a.getClass.getMethod("cat",hi.getClass,all.getClass)
method.invoke(a,hi,all)


Scala를 통해서 하고자 한다면..

case class Caller[T>:Null<:AnyRef](klass:T) {
  def call(methodName:String,args:AnyRef*):AnyRef = {
    def argtypes = args.map(_.getClass)
    def method = klass.getClass.getMethod(methodName, argtypes: _*)
    method.invoke(klass,args: _*)
  }
}
implicit def anyref2callable[T>:Null<:AnyRef](klass:T):Caller[T] = new Caller(klass)
a call ("cat","Hi","there")
이러하다..


저작자 표시 비영리 변경 금지
신고

[javascript] convert underscore to camelcase

Programming 2015.05.29 14:47

var a = ["animal_cat","animal_dog","animal_lion"];

for(var i = 0 ; i < a.length ; i++){

a[i] = a[i].replace(/_([a-z])/g, function (g) { return g[1].toUpperCase(); });

}


저작자 표시 비영리 변경 금지
신고

[scala] Pattern matching / Type matching

Programming/scala 2015.04.08 14:03

스칼라를 쓰면서 이해하는데 많은 공이 들어가는게 matching이다.


매칭을 쓰다가 괴팍한 문제에 부닥혔다.

type matching을 이용하여 case문을 쓰려고 한 코드다.

val t = ("string", Int)


t match {

case t:(String, String) => println("second value is string")

case t:(String, Int) => println("second value is int")

case _ => println("others.")

}


이렇게 하면 두번째 매칭인 (String,Int)에 매칭이되어 "second value is int"가  나와야 할것 같은데.. 첫번째인 "second value is string" 가 나온다.

그러면서 워닝이 뜨지.

<console>:10: warning: fruitless type test: a value of type (String, Int) cannot also be a (String, String) (but still might match its erasure)

              case t:(String, String) => println("second value is string")

                     ^

<console>:11: warning: unreachable code

              case t:(String, Int) => println("second value is int")

이는 튜플의 제네릭 타입 추론이 불가능해서 인걸로 추측이 되는데..

t match ...  요부분에서 t의 타입을 정해주지 않았기에 컴파일러가 튜플 내의 타입을 추론하지 못한것 같다.

만약에 tuple이 val t = ("string", 0) 이렇게 되어있다면

아래와 같은 type matching이 가능하다.

(t: (Any, Any))  match {

  case (t1: String, t2: String) => "this is string"

  case (t1: String, t2: Int) => "this is int"

  case _ => "this is other!"

}

왠지 위의 코드로 원래의 문제였던 val t = ("string", Int)를 넣으면 제대로 매칭할 것 같지만.. 실제로 돌려보면 아니다...

실제로 돌려보면 아무것도 매칭되지 않아서 "this is other!"가 출력된다.


이를통해서 하나의 tuple내에서 type matching과 pattern matching이 병합적으로 사용되지 못함을 알 수 있다.

Int의 type은 Int가 아니고 object scala.Int이기 때문이다.


결국은 type matching으로 해결하기 힘들게 되어 나온코드는 pattern matching을 사용하는 코드였다.

val t = ("string", Int)

t._2 match {

case Float => "this is Float"

case Int => "this is Integer"

case _ => "this is other!"

}


두번째 인자인 Int == Int 이기 때문이다.

하지만 이것도 근본적인 해결책은 아니다. 왜냐하면

val t = ("string", "string val") 형태로 들어온것을 잡아내기 위해서는 

case "string val" 이라고 명시되어야 하기 때문이다.

case String 이라고 쓸수 없으니까...

결국 제일 마지막의 _ 에 걸릴수 밖에 없다.





저작자 표시 비영리 변경 금지
신고

[ROR] benchmark sort

Programming 2014.07.02 17:18

#!/usr/bin/ruby 

require 'benchmark' 

ary = [] 
1000.times { 
 ary << {:bar => rand(1000)} 


n = 500 
Benchmark.bm(20) do |x| 
 x.report("sort")               { n.times { ary.sort{ |a,b| b[:bar] <=> a[:bar] } } } 
 x.report("sort reverse")       { n.times { ary.sort{ |a,b| a[:bar] <=> b[:bar] }.reverse } } 
 x.report("sort_by -a[:bar]")   { n.times { ary.sort_by{ |a| -a[:bar] } } } 
 x.report("sort_by a[:bar]*-1") { n.times { ary.sort_by{ |a| a[:bar]*-1 } } } 
 x.report("sort_by.reverse!")   { n.times { ary.sort_by{ |a| a[:bar] }.reverse } } 
end 



                           user     system      total        real

sort                   0.940000   0.000000   0.940000 (  0.940155)

sort reverse           0.970000   0.000000   0.970000 (  0.969526)

sort_by -a[:bar]       0.390000   0.010000   0.400000 (  0.400547)

sort_by a[:bar]*-1     0.390000   0.000000   0.390000 (  0.391629)

sort_by.reverse!       0.370000   0.000000   0.370000 (  0.373811)


저작자 표시 비영리 변경 금지
신고

[ROR] rails generate not null 제약조건 변경.

Programming 2014.06.18 11:20


> rails g migration change_field_name_to_table_name field_name:data_type


class ChangeFieldNameToTableName < ActiveRecord::Migration

  def change

    change_column_null(:table_name, :field_name, true)

  end

end






저작자 표시 비영리 변경 금지
신고

[ROR] ActiveRecord module - create on duplicate key update

Programming 2014.03.03 22:13

module ActiveRecord

  # = Active Record Persistence

  module Persistence

    extend ActiveSupport::Concern


    def create_on_duplicate_key_update!(keys)

      #keys = duplicate_keys.is_a? Array ? duplicate_keys : [duplicate_keys] 

      keys.collect! { |k| k.to_s }

      klass = self.class

      attributes_with_values = arel_attributes_with_values_for_create(attribute_names)

      column_hash = klass.connection.schema_cache.columns_hash klass.table_name

      db_columns_with_values = []

      attributes_with_values.map { |attr, value|

        real_column = column_hash[attr.name]

        db_columns_with_values << [real_column, value] if value.present?

        if (value.blank? && ['created_at', 'updated_at'].include?(real_column.name))

          now = DateTime.now

          db_columns_with_values << [real_column, now]

          self.send("#{attr.name}=",now)

        end

      }

      sql = "INSERT INTO #{self.class.quoted_table_name} (#{db_columns_with_values.collect{|c| klass.connection.quote_column_name(c.first.name)}.join(', ')})"

      sql << " VALUES (#{db_columns_with_values.collect{|c| klass.connection.quote(c.last)}.join(', ')}) "

      sql << " ON DUPLICATE KEY UPDATE "

      sql << sql_for_on_duplicate_key_update(keys,db_columns_with_values)


      klass.connection.execute sql

    end


    private

    def sql_for_on_duplicate_key_update(keys,db_columns_with_values)

      connection = self.class.connection

      results = []

      db_columns_with_values.map do |column, value|

        results << "#{self.class.quoted_table_name}.#{connection.quote_column_name(column.name)}=#{connection.quote(value, column)}" unless keys.include?(column.name)

      end

      results.join(',')

    end

  end

end



저작자 표시 비영리 변경 금지
신고

[ROR 팁]Rails rake test에서 특정 기능만 테스트하기!

Programming 2014.02.26 16:59

rake test를 돌릴 때 원하는 기능의 테스트들만 한번에 돌리고자 할 때... 유용한 팁


만약 디렉토리가


test/controllers/blog_controller_test.rb

test/models/blog_model_test.rb

test/jobs/blog_job_test.rb 

...


이런식으로 작성이 되었다면 blog에 관련된 테스트만 돌리고싶다! 는 needs다.


namespace :test do

  rule "" do |t|

    # rake test:blog

    if /test:(.*)(:([^.]+))?$/.match(t.name)

      arguments = t.name.split(":")[1..-1]

      file_name = arguments.first

      test_name = arguments[1..-1]


      Dir["test/**/#{file_name}*_test.rb"].each {|path|

        result = `ruby -Ilib:test #{path}`

        puts "=========[ #{file_name} test result ]================================================================"

        puts result[result.index("Finished tests")..-1].to_s.split('\n')

        puts "==========================================================================================="

      }

    end

  end

end




아무 .rake 파일을 만들어서 lib/tasks 밑에 넣어주면 된다.

저작자 표시 비영리 변경 금지
신고


티스토리 툴바