728x90
반응형

아래의 예시 자료는 hostgator.com/help/article/의 내용을 참조로 하였음을 밝힙니다.

(출처 :  https://www.hostgator.com/help/article/apache-mod-rewrite-and-examples )

 

https://httpd.apache.org/docs/trunk/rewrite/intro.html

 

Apache mod_rewrite Introduction - Apache HTTP Server Version 2.5

Apache mod_rewrite Introduction This document supplements the mod_rewrite reference documentation. It describes the basic concepts necessary for use of mod_rewrite. Other documents go into greater detail, but this doc should help the beginner get their fee

httpd.apache.org

 

https://httpd.apache.org/docs/trunk/mod/mod_rewrite.html

 

mod_rewrite - Apache HTTP Server Version 2.5

Apache Module mod_rewrite Summary The mod_rewrite module uses a rule-based rewriting engine, based on a PCRE regular-expression parser, to rewrite requested URLs on the fly. By default, mod_rewrite maps a URL to a filesystem path. However, it can also be u

httpd.apache.org

 

 

 

Regex vocabulary

CharacterMeaningExample

. Matches any single character ( 한글자 매칭) c.t will match cat, cot, cut, etc
+ Repeats the previous match one or more times
( 첫글자로 시작하면서 반복하는 경우)
a+ matches a, aa, aaa, etc
* Repeats the previous match zero or more times
( 임의의 길이의 글자(/기호)들 )
a* matches all the same things a+ matches, but will also match an empty string
? Makes the match optional
(앞글자를 지울지? 말지?)
colou?r will match color and colour
\ Escape the next character
(이스케이프 문자 처리할 때 )
\. will match . (dot) and not any single character as explain above
^ Called an anchor, matches the beginning of the string
(첫글자가 ^뒤에 오는 글자인 경우)
^a matches a string that begins with a
$ The other anchor, this matches the end of the string
(마지막 글자가 $ 앞에 있는 글자인 경우)
a$ matches a string that ends with a
( ) Groups several characters into a single unit, and captures a match for use in a backreference
( 지정한 복수개의 글자들 단위  지정)
(ab)+ matches ababab - that is, the + applies to the group. For more on backreferences see below
[ ] A character class - matches one of the characters
( ~중에 한 글자 )
c[uoa]t matches cut, cot or cat
[^  ]  Negative character class - matches any character not specified
( ~의 글자가 아닌 경우)
c[^/]t matches cat or c=t but not c/t

 

 

 

Regex Back-Reference Availability

해석

   (  ) 로 묶인 그룹캐릭터를은   $N 또는 %N   즉,  달러 N 또는 퍼센티지 N으로 지칭될 수 있다.

   ([a-z]+)  는   Rule에 있으므로   $ 로 받을 수 있으며,  인덱스는 1이다.  그래서 결국  $1 이다.   임의의 길이의 알파벳...

   (.*) 는 임의길이의 글자/숫자/기호  를 나타내며  $2로 받는다.

  (admin.example.com)은  새로운 단위지정이고,  Cond 에 있으므로 %(퍼센티지)로 받아서 %1 이된다.

  결국,  /test/1234   로 요청이 오면,    /admin.foo?page=test&id=1234&host=admin.example.com. 로 변형한다.

 

 

RewriteRule Basics

 

RewriteRule Pattern Substitution Flags 또는

RewriteRule Pattern target Flags

 

 

 

 

       Substitution         

 

1. A full filesystem path to a resource 

RewriteRule "^/games" "/usr/local/games/web/puzzles.html"

        요청을  /usr/local/games/web/puzzles.html 로 매핑. 즉, 임임의 파일시스템의 리소스로 연결 가능

 

2. A web-path to a resource

RewriteRule "^/games$" "/puzzles.html"

         웹 서비스의 패스 기준으로 연결.( DocumentRoot 가 지정되어 있을 경우.)

        http://example.com/games   ->     /usr/local/apache2/htdocs/puzzles.html 

 

3. An absolute URL

RewriteRule "^/product/view$" "http://site2.example.com/seeproduct.html" [R]

           특정 URL로 새로운 요청을 처리한다.

 

 

   Rewrite Conditions      

      1개 이상의  RewriteCond 이라는 Directive를 사용할 수 있다.  요청에 대해 한정된 조건을 체크한다. 뒤 따르는 RewriteRule을 한정한다.

RewriteCond "%{REMOTE_ADDR}" "^10\.2\."
RewriteRule "(.*)"           "http://intranet.example.com$1"

      10.2.  로 시작하는 IP에 대한 요청은 무조건  http://intranet.example.com 쪽으로 돌린다.

 

 

RewriteCond "%{QUERY_STRING}" "hack"
RewriteCond "%{HTTP_COOKIE}"  !go
RewriteRule "."               "-"   [F]

   복수 개의 RewriteCond 조건은  && 이다. 즉 2개 다 만족하여야 한다. 

 

 

RewriteCond "%{HTTP_HOST}" "(.*)"
RewriteRule "^/(.*)"       "/sites/%1/$1"

  요청이   http://example.com/foo/bar  일 경우,    %1의 값은  example.com 이 되고,   $1의 값은 foo/bar 가 된다.

  이에    최종적으로  http://example.com/site/example.com/foo/bar 로  연결시킨다.

 

 

 

Server-Variables

HTTP headers

connection & request:

server internals:

date and time:

specials:

HTTP_ACCEPT
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST
HTTP_PROXY_CONNECTION
HTTP_REFERER
HTTP_USER_AGENT
AUTH_TYPE
CONN_REMOTE_ADDR
CONTEXT_PREFIX
CONTEXT_DOCUMENT_ROOT
IPV6
PATH_INFO
QUERY_STRING
REMOTE_ADDR
REMOTE_HOST
REMOTE_IDENT
REMOTE_PORT
REMOTE_USER
REQUEST_METHOD
SCRIPT_FILENAME
 
DOCUMENT_ROOT
SCRIPT_GROUP
SCRIPT_USER
SERVER_ADDR
SERVER_ADMIN
SERVER_NAME
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE
TIME_YEAR
TIME_MON
TIME_DAY
TIME_HOUR
TIME_MIN
TIME_SEC
TIME_WDAY
TIME
API_VERSION
CONN_REMOTE_ADDR
HTTPS
IS_SUBREQ
REMOTE_ADDR
REQUEST_FILENAME
REQUEST_SCHEME
REQUEST_URI
THE_REQUEST

 

 

 

 

 

Redirect All Website Pages

# Redirect all pages from olddomain.com
# to newdomain.com
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www.olddomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^olddomain.com$
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]

해석 

   예로써   http://www.oldmain.com/aaa.html    은   http://www.newdomain.com/aaa.html   로  Redirect 함.

   aaa.html 이   $1 인 듯.  즉   ^(.*)    를  $1으로 받아서 전달함.

   HTTP  HOST가   www.olddomain.com   또는(OR)  olddomain.com  일 경우,....

 

 

 

RewriteCond  "%{HTTP_USER_AGENT}"  "(iPhone|Blackberry|Android)"
RewriteRule  "^/$"                 "/homepage.mobile.html"  [L]

RewriteRule  "^/$"                 "/homepage.std.html"     [L]

모바일 단말기 일때는 모바일 웹페이지로, 아니면 기본으로  std 웹페이지로....

 

 

 

F|forbidden   Flag

RewriteRule "\.exe"   "-" [F]

  .exe file에 대한 접근을 막는다,  단순히 응답을 403으로 리턴하게 된다. 

 target에 "-" 은   target에 대해  URI를 변경하지 않는다 즉 No Substitution이 된다.

 

 

 

S|skip

# Does the file exist?
RewriteCond "%{REQUEST_FILENAME}" !-f
RewriteCond "%{REQUEST_FILENAME}" !-d
# Create an if-then-else construct by skipping 3 lines if we meant to go to the "else" stanza.
RewriteRule ".?"                  "-" [S=3]

# IF the file exists, then:
    RewriteRule "(.*\.gif)"  "images.php?$1"
    RewriteRule "(.*\.html)" "docs.php?$1"
    # Skip past the "else" stanza.
    RewriteRule ".?"         "-" [S=1]
# ELSE...
    RewriteRule "(.*)"       "404.php?file=$1"
# END

 

P|Proxy

RewriteRule "/(.*)\.(jpg|gif|png)$" "http://images.example.com/$1.$2" [P]

 

NC|nocase

RewriteRule "(.*\.(jpg|gif|png))$" "http://images.example.com$1" [P,NC]

  .jpg and .JPG 모두 프락시(P)로 처리된다.

 

NE|noescae

RewriteRule "^/anchor/(.+)" "/bigpage.html#$1" [NE,R]

    /anchor/xyz  를   /bigpage.html#xyz  로 리다이렉트시킨다.      # 같은 기호를 hexacode(%23)로 변환하지 않는다.

 

 

 

728x90
반응형
728x90
반응형

구글 검색을 유도하기 위해서는 URL을 유도하여야 합니다.

유도 대상 URL을 iframe 태그를 사용하여 수행하니, 3-4일이 지나도 구글검색이 되지 않았습니다.

 

추가로 문서를 탐색하여, https://developers.google.com/search/docs/crawling-indexing/links-crawlable?hl=en 

 

크롤링할 수 있는 링크 만들기 | Google 검색 센터  |  문서  |  Google Developers

Google에서는 href 속성이 포함된 유효한 a 태그인 경우에만 링크를 크롤링할 수 있습니다. 예시를 살펴보고 크롤링 가능한 링크인지 확인하세요.

developers.google.com

  에서는 아래 그림 1과 같이 소개하고 있습니다.

그림 1. 구글 검색 즉 구글측에서 크롤링할 수 있게 하려면, URL을 <a> 태그를 명확히 잘 사용하여야 한다고 합니다.

 

이에 조치방법을 적용해 보았습니다.

 

<html>
<style>
	.klaudGoogleARefHidden {
		display: none; 
}
</style>

<body>
	<a href="http://speech.pe.kr/20221226000001.html"> 뉴스 2022  </a>
	</div>
</body>
</html>

로 구현한 후, 수행하면

 

그림 2, <a>링크가 제대로 나타나 보임,  링크를 누르면 구글 검색 대상 URL이 나타남.

 

이제는 태그를 숨기면 됩니다.  iframe으로 숨김을 대체하기 위해서  tag 요소를 숨겨야 합니다.

<html>
<style>
	.klaudGoogleARefHidden {
		display: none; 
	}
</style>

<body>
	<div class="klaudGoogleARefHidden">
	<a href="http://speech.pe.kr/20221226000001.html"> 뉴스 2022  </a>
	</div>
</body>
</html>

로 구현한 후, 수행하면 (  <div class="" 가 추가됨. )

 

그림 3. 태그가 숨겨짐.

 

 

구글에서 목적한 웹페이지를 제대로 크롤링 및 인덱싱되어 검색이 되는지...를 며칠 더 기다려 보아야 할 것 같습니다.

 

728x90
반응형
728x90
반응형

a_ict_word라는 클래스 이름으로 된 모든 span 요소를 제거하여, 문장 내에서 특정 단어를 강조하는 역할로 삽입된 요소를 제거하여, 끊김 없는 문장을 추출하는 프로그램입니다. 다소 규칙기반적인 사항으로 작성되었습니다.

 

if ( document.querySelectorAll('.a_ict_word') != undefined) {

        const spanElms =  document.querySelectorAll('.a_ict_word');

		if( spanElms.length > 0 ) {
			var parentIDArray = new Array( spanElms.length );
           	var parentID = 0;
        	parentIDArray[0] = parentID;
        	previousParent = spanElms[0].parentNode;
        	for( ii =1; ii<spanElms.length; ii++){
        		currentParent = spanElms[ii].parentNode;
        		parentIDArray[ii] = parentID;
        		if( currentParent != previousParent){
        			previousParent = currentParent;
        			parentIDArray[ii] = ++parentID;
        		}
        	}	
		}	

        jj=0;
        for( jj = 0; jj<spanElms.length; jj++){
            if( spanElms[jj].previousSibling != undefined && spanElms[jj].nextSibling != undefined && spanElms[jj].childNodes[0] != undefined ){
                 makeSentence = spanElms[jj].previousSibling.textContent.replace(/^\s+|\s+$/g,"")  + " "+ spanElms[jj].childNodes[0].textContent.replace(/^\s+|\s+$/g,"") + spanElms[jj].nextSibling.textContent.replace(/^\s+|\s+$/g,"");
                 spanElms[jj].previousSibling.textContent = makeSentence;
                 spanElms[jj].childNodes[0].textContent ="";
                 spanElms[jj].nextSibling.textContent="";
				
				if( spanElms[jj].nextSibling && spanElms[jj].nextSibling.nextSibling && spanElms[jj].nextSibling.nextSibling.textContent){
                      	if( spanElms[jj].nextSibling.nextSibling.textContent.indexOf('<br>') || spanElms[jj].nextSibling.nextSibling.textContent.indexOf('</p>' ) || spanElms[jj].nextSibling.nextSibling.textContent.indexOf("''" ) || spanElms[jj].nextSibling.nextSibling.textContent.length == 0 ){
                           		continue;
                       	} 
						if( (spanElms[jj].nextSibling.nextSibling.tagName) && (spanElms[jj].nextSibling.nextSibling.tagName == "BR") )
                           		continue;
						}

						if( spanElms[jj].nextSibling.nextSibling == undefined )
                                continue;
                                
                        for( kk=jj ; kk <spanElms.length; kk++ ){
								if( parentIDArray[ jj ] != parentIDArray[ jj + kk ] )
                                	break;

						if( spanElms[jj + kk ] && spanElms[jj + kk ].previousElementSibling ){
                           	    if( spanElms[jj + kk ].previousElementSibling.nodeName == 'BR' )
                        			break;	 		                                		 
                               	}

                                if( spanElms[jj + kk ] && spanElms[jj + kk ].nextElementSibling ) {
		                                if(  spanElms[jj + kk ].nextElementSibling.className === 'a_ict_word'){
		                                		 spanElms[jj ].previousSibling.textContent += spanElms[jj + kk ].nextElementSibling.childNodes[0].textContent;
		                                 		 spanElms[jj + kk ].nextElementSibling.childNodes[0].textContent="";
		                                 		 
		                                 		 spanElms[jj ].previousSibling.textContent += spanElms[jj + kk ].nextElementSibling.nextSibling.textContent;
		                                 		 spanElms[jj + kk ].nextElementSibling.nextSibling.textContent ="";       	 	
		                                }
	                              }
                        }
                              
              }
              else if(  spanElms[jj].previousSibling == undefined && spanElms[jj].nextSibling != undefined ){
                        makeSentence = spanElms[jj].childNodes[0].textContent.replace(/^\s+|\s+$/g,"") + spanElms[jj].nextSibling.textContent.replace(/^\s+|\s+$/g,"");
                        spanElms[jj].childNodes[0].textContent = "";
                        spanElms[jj].nextSibling.textContent=makeSentence;
              }
        }
 }
728x90
반응형
728x90
반응형

1. 목적

특정 프로그램 서비스를 구동할 때, root 계정으로 수행시 해당 로그파일도 root계정으로 생성됨.

유지보수 측면에서 로그파일 점검은 root계정을 부여하지 않는 낮은 권한의 계정으로 분석을 수행함.

이에, 로그로테이션 로그파일에 대해 특정계정으로 로그파일을 생성함.

 

2. 설명

- RotatingFileHandler함수를 상속하여야 함. ( TimedRoatingFileHandler 아님.)

- shouldRollover()를 overriding하여야 함.

- 날마다 또는 시/분 등으로 로그파일을 rotation시키고자 할 경우, 그 단위를 직접 구현하여야 함.(파일명)::getBaseFileName()참조

- 변경된 파일명을 부모 클래스인 RotatingFIleHandler()에게 넘김.

- Ownership변경은 파일명이 생성될 때, shell util 함수를 사용하여 변경한다.

- 아래 포스팅된 코드는 시분 단위로 구현하여, 짧은 시간에 점검이 가능함. ( 필요시, 날마다로 변경 가능)

- 구현단계에서 고민하였던 코드는 주석처리하여 보존함.

- TimedRoatingFile에 대한 callback을 처리하는 것은 동작하지 않는 것으로 파악됨.

3. 참조

본 포스팅은 https://www.py4u.net/discuss/193456 를 참조로 하였음.

추가적으로 구현하여, 상기 포스팅 자료와 달리, 전체 프로그램을 단독으로 수행가능함.(핸들러 지정/연결 등)

파일모드로 로그환경변수를 지정하는 대신에, dictionary형태로 지정함.

 

```​

from logging import handlers

import logging

import logging.config

import datetime

import time

import os

import shutil

class DailyRotatingFileHandler(handlers.RotatingFileHandler):

def __init__( self, alias, basedir, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0 ):

#def __init__( self, alias, basedir, filename, when='h', interval=1, backupCount=0, encoding=None, delay=0, utc=0, atTime=None, errors=None):

self.basedir_ = basedir

self.alias_ = alias

self.baseFilename = self.getBaseFileName()

print("baseFileName = %s\n" % self.baseFilename )

handlers.RotatingFileHandler.__init__(self, self.baseFilename, mode, maxBytes, backupCount, encoding, delay )

#handlers.TimedRotatingFileHandler.__init__(self, self.baseFilename, when='m', interval=1 )

 

def getBaseFileName(self):

#self.today_ = datetime.date.today()

#basename_ = self.today_.strftime("%Y-%m-%d") + ".log" + '.' + self.alias_

self.today_ = datetime.date.today()

tm = time.localtime()

self.hour_ = str( tm.tm_hour )

self.minute_ = '%02d' % tm.tm_min

basename_ = self.today_.strftime("%Y-%m-%d") + "_" + self.hour_ + "_" + self.minute_ + ".log"

filename = os.path.join(self.basedir_, basename_)

'''

Change owner

'''

#if not os.path.exists(filename):

# open(filename, 'a').close()

#group = 'klaud'

#shutil.chown(filename, group, group)

 

return filename

 

def shouldRollover(self, record):

print("#### in the shouldRollover() ####")

#print(record);

 

if self.stream is None:

print("#### file.open() ####")

self.stream = self._open()

#if self.maxBytes > 0:

# msg = "%s\n" % self.format(record)

# self.stream.seek(0, 2)

# if( self.stream.tell() + len(msg)) >= self.maxBytes:

# return 1

 

#if self.today_ != datetime.date.today():

# self.baseFilename = self.getBaseFileName()

# return 1

tm = time.localtime()

if self.minute_ != str( tm.tm_min ):

self.baseFilename = self.getBaseFileName()

return 1

 

return 0

 

 

if __name__ == '__main__':

config ={

"version": 1,

"formatters": {

"simple": {"format": "[%(name)s] %(message)s"},

"complex": {

"format": "%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] - %(message)s"

},

},

"handlers": {

"console": {

"class": "logging.StreamHandler",

"formatter": "simple",

"level": "INFO",

},

"file": {

#"class": "logging.FileHandler",

#"filename": "error.log",

#"formatter": "complex",

#"level": "ERROR",

#'()': owned_file_handler,

#'owner': ['klaud', 'klaud'],

'level': 'INFO',

#'class': 'logging.handlers.TimedRotatingFileHandler',

#'class': 'TimedRotatingFileHandler',

'class' : 'logging.handlers.RotatingFileHandler',

#'when': 'M',

#'backupCount': 8,

#'filename': f'/home/klaud/logs/aaa.log',

'filename': f'timed_test_kkkk.log',

 

},

},

"root": {"handlers": ["console", "file"], "level": "INFO"},

"loggers": {"parent": {"level": "INFO"}, "parent.child": {"level": "DEBUG"},},

}

 

 

log_file = "timed_test.log"

#logging.config.fileConfig('logging.conf')

logging.config.dictConfig(config)

logger = logging.getLogger("root")

#logger = logging.getLogger("sLogger")

logger.setLevel(logging.INFO)

#create_timed_rotation_log(log_file)

#print("## Calling : owned_file_handler")

#handler = owned_file_handler(log_file, "klaud", when='m',

# interval=1

# );

#handler = TimedRotatingFileHandler( path,

# when="m",

# interval=1,

# backupCount=5)

handler = DailyRotatingFileHandler("alias", "./")

logger.addHandler(handler)

for i in range(6):

#logger.info("[%s]This is a test!", datetime.datetime.now().strftime("%H:%M:%S") )

logger.info("This is a test!" )

time.sleep(65)

 

```

수행 결과 예시

[root@localhost sahngwoon]# ls -al

합계 76

drwxr-xr-x 6 root root 4096 11월 23 11:21 .

drwxr-xr-x. 5 root root 4096 11월 22 16:40 ..

-rw-r--r-- 1 klaud klaud 16 11월 23 11:15 2021-11-23_11_15.log

-rw-r--r-- 1 klaud klaud 16 11월 23 11:17 2021-11-23_11_17.log

-rw-r--r-- 1 klaud klaud 16 11월 23 11:18 2021-11-23_11_18.log

-rw-r--r-- 1 klaud klaud 16 11월 23 11:19 2021-11-23_11_19.log

-rw-r--r-- 1 klaud klaud 16 11월 23 11:20 2021-11-23_11_20.log

-rw-r--r-- 1 klaud klaud 16 11월 23 11:21 2021-11-23_11_21.log

-rw-r--r-- 1 root root 267 11월 16 13:23 ReverseString.java

 

728x90
반응형

+ Recent posts