Apache2.2和Tomcat5.0的整合(二)—解决REDIRECT_URL的中文路径问题

  • 现象

通过mod_jk整合Apache和Tomcat,在Servlet中可以通过request.getAttribute("REDIRECT_URL")获得Apache自定义错误处理的原始URL。
不幸的是,如果这个REDIRECT_URL包含中文路径,我们获得的将是乱码。
例如:请求不存在的页面http://localhost/rp/数字故宫/hh.html,
返回结果为:/rp/数字故宫/hh.html
  • 问题定位
问题出在哪里呢?
作以下测试:
在Apache的httpd.conf加入如下两行
JkEnvVar DPM1 %e6%95%b0%e5%ad%97%e6%95%85%e5%ae%ab
JkEnvVar DPM2 数字故宫
结果第一行返回: %e6%95%b0%e5%ad%97%e6%95%85%e5%ae%ab
第二行返回: 数字故宫
即jk本身不能正确将环境变量的中文值送到request.getAttribute

下载mod_jk源代码http://tomcat.apache.org/download-connectors.cgi
通过代码分析、日志跟踪,确定Apache送到jk的REDIRECT_URL值为utf-8编码
此变量值经过jk_b_append_string函数写入到缓冲后,通过socket8009发送给tomcat之后,
再经过tomcat接收分析之后,出现乱码。
  • 解决办法
解决办法,既然jk处理西文没有问题,何不将中文URL进行URLEnocode
从网上收到urlencode的C实现:
c# 代码
 
  1. static unsigned char hexchars[] = "0123456789ABCDEF";  
  2.   
  3. char *urlencode(char *s)  
  4. {  
  5.     register int x, y;  
  6.     unsigned char *str;  
  7.     int len=strlen(s);  
  8.   
  9.     str = (unsigned char *) malloc(3 * strlen(s) + 1);  
  10.     for (x = 0, y = 0; len--; x++, y++) {  
  11.         str[y] = (unsigned char) s[x];  
  12.         if (str[y] == ' ') {  
  13.             str[y] = '+';  
  14. #ifndef CHARSET_EBCDIC  
  15.         } else if ((str[y] < '0' && str[y] != '-' && str[y] != '.') ||  
  16.                    (str[y] < 'A' && str[y] > '9') ||  
  17.                    (str[y] > 'Z' && str[y] < 'a' && str[y] != '_') ||  
  18.                    (str[y] > 'z')) {  
  19.             str[y++] = '%';  
  20.             str[y++] = hexchars[(unsigned char) s[x] >> 4];  
  21.             str[y] = hexchars[(unsigned char) s[x] & 15];  
  22.         }  
  23. #else /*CHARSET_EBCDIC*/  
  24.         } else if (!isalnum(str[y]) && strchr("_-.", str[y]) == NULL) {  
  25.             /* Allow only alphanumeric chars and '_', '-', '.'; escape the rest */  
  26.             str[y++] = '%';  
  27.             str[y++] = hexchars[os_toascii[(unsigned char) s[x]] >> 4];  
  28.             str[y] = hexchars[os_toascii[(unsigned char) s[x]] & 0x0F];  
  29.         }  
  30. #endif /*CHARSET_EBCDIC*/  
  31.     }  
  32.   
  33.   
  34.     str[y] = '\0';  
  35.     return ((char *) str);  
  36. }  
将ajp_marshal_into_msgb函数体发送属性部分进行修改,修改后的代码为:
cpp 代码
 
  1.  if (s->num_attributes > 0) {  
  2.      for (i = 0; i < s->num_attributes; i++) {  
  3. //c4w  
  4. char * pval=s->attributes_values[i];  
  5. char * url=NULL;  
  6. if(strcmp(s->attributes_names[i],"REDIRECT_URL")==0){  
  7.     url=urlencode(s->attributes_values[i]);  
  8.     //pval=url;  
  9. }  
  10.          if (jk_b_append_byte(msg, SC_A_REQ_ATTRIBUTE) ||  
  11.              jk_b_append_string(msg, s->attributes_names[i]) ||  
  12.              jk_b_append_string(msg, pval)) {  
  13.              jk_log(l, JK_LOG_ERROR,  
  14.                     "failed appending attribute %s=%s",  
  15.                     s->attributes_names[i], pval);  
  16.              JK_TRACE_EXIT(l);  
  17.              return JK_FALSE;  
  18.          }  
  19. if(url!=NULL) free(url);  
  20.      }  
  21.  }  

最后,在jsp中对REDIRECT_URL进行解码
String url=URLDecoder.decode((String)request.getAttribute("REDIRECT_URL"),"utf-8");
  • 结论
编译,启动tomcat,重新请求不存在的页面http://localhost/rp/数字故宫/hh.html,返回结果为:/rp/数字故宫/hh.html
看到了了正确的结果:/rp/数字故宫/hh.html

你可能感兴趣的:(apache,html,tomcat,OS,REST)