comparison src/http/modules/ngx_http_proxy_module.c @ 4925:32030fa8cb14

Request body: chunked parsing moved to ngx_http_parse.c from proxy. No functional changes.
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 21 Nov 2012 00:59:16 +0000
parents 8036fc6af2df
children 93294110728f
comparison
equal deleted inserted replaced
4924:caca5603bded 4925:32030fa8cb14
79 } ngx_http_proxy_loc_conf_t; 79 } ngx_http_proxy_loc_conf_t;
80 80
81 81
82 typedef struct { 82 typedef struct {
83 ngx_http_status_t status; 83 ngx_http_status_t status;
84 ngx_http_chunked_t chunked;
84 ngx_http_proxy_vars_t vars; 85 ngx_http_proxy_vars_t vars;
85 size_t internal_body_length; 86 size_t internal_body_length;
86
87 ngx_uint_t state;
88 off_t size;
89 off_t length;
90 87
91 ngx_uint_t head; /* unsigned head:1 */ 88 ngx_uint_t head; /* unsigned head:1 */
92 } ngx_http_proxy_ctx_t; 89 } ngx_http_proxy_ctx_t;
93 90
94 91
1250 1247
1251 ctx->status.code = 0; 1248 ctx->status.code = 0;
1252 ctx->status.count = 0; 1249 ctx->status.count = 0;
1253 ctx->status.start = NULL; 1250 ctx->status.start = NULL;
1254 ctx->status.end = NULL; 1251 ctx->status.end = NULL;
1255 ctx->state = 0; 1252 ctx->chunked.state = 0;
1256 1253
1257 r->upstream->process_header = ngx_http_proxy_process_status_line; 1254 r->upstream->process_header = ngx_http_proxy_process_status_line;
1258 r->upstream->pipe->input_filter = ngx_http_proxy_copy_filter; 1255 r->upstream->pipe->input_filter = ngx_http_proxy_copy_filter;
1259 r->upstream->input_filter = ngx_http_proxy_non_buffered_copy_filter; 1256 r->upstream->input_filter = ngx_http_proxy_non_buffered_copy_filter;
1260 r->state = 0; 1257 r->state = 0;
1615 1612
1616 return NGX_OK; 1613 return NGX_OK;
1617 } 1614 }
1618 1615
1619 1616
1620 static ngx_inline ngx_int_t
1621 ngx_http_proxy_parse_chunked(ngx_http_request_t *r, ngx_buf_t *buf)
1622 {
1623 u_char *pos, ch, c;
1624 ngx_int_t rc;
1625 ngx_http_proxy_ctx_t *ctx;
1626 enum {
1627 sw_chunk_start = 0,
1628 sw_chunk_size,
1629 sw_chunk_extension,
1630 sw_chunk_extension_almost_done,
1631 sw_chunk_data,
1632 sw_after_data,
1633 sw_after_data_almost_done,
1634 sw_last_chunk_extension,
1635 sw_last_chunk_extension_almost_done,
1636 sw_trailer,
1637 sw_trailer_almost_done,
1638 sw_trailer_header,
1639 sw_trailer_header_almost_done
1640 } state;
1641
1642 ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1643
1644 if (ctx == NULL) {
1645 return NGX_ERROR;
1646 }
1647
1648 state = ctx->state;
1649
1650 if (state == sw_chunk_data && ctx->size == 0) {
1651 state = sw_after_data;
1652 }
1653
1654 rc = NGX_AGAIN;
1655
1656 for (pos = buf->pos; pos < buf->last; pos++) {
1657
1658 ch = *pos;
1659
1660 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1661 "http proxy chunked byte: %02Xd s:%d", ch, state);
1662
1663 switch (state) {
1664
1665 case sw_chunk_start:
1666 if (ch >= '0' && ch <= '9') {
1667 state = sw_chunk_size;
1668 ctx->size = ch - '0';
1669 break;
1670 }
1671
1672 c = (u_char) (ch | 0x20);
1673
1674 if (c >= 'a' && c <= 'f') {
1675 state = sw_chunk_size;
1676 ctx->size = c - 'a' + 10;
1677 break;
1678 }
1679
1680 goto invalid;
1681
1682 case sw_chunk_size:
1683 if (ch >= '0' && ch <= '9') {
1684 ctx->size = ctx->size * 16 + (ch - '0');
1685 break;
1686 }
1687
1688 c = (u_char) (ch | 0x20);
1689
1690 if (c >= 'a' && c <= 'f') {
1691 ctx->size = ctx->size * 16 + (c - 'a' + 10);
1692 break;
1693 }
1694
1695 if (ctx->size == 0) {
1696
1697 switch (ch) {
1698 case CR:
1699 state = sw_last_chunk_extension_almost_done;
1700 break;
1701 case LF:
1702 state = sw_trailer;
1703 break;
1704 case ';':
1705 case ' ':
1706 case '\t':
1707 state = sw_last_chunk_extension;
1708 break;
1709 default:
1710 goto invalid;
1711 }
1712
1713 break;
1714 }
1715
1716 switch (ch) {
1717 case CR:
1718 state = sw_chunk_extension_almost_done;
1719 break;
1720 case LF:
1721 state = sw_chunk_data;
1722 break;
1723 case ';':
1724 case ' ':
1725 case '\t':
1726 state = sw_chunk_extension;
1727 break;
1728 default:
1729 goto invalid;
1730 }
1731
1732 break;
1733
1734 case sw_chunk_extension:
1735 switch (ch) {
1736 case CR:
1737 state = sw_chunk_extension_almost_done;
1738 break;
1739 case LF:
1740 state = sw_chunk_data;
1741 }
1742 break;
1743
1744 case sw_chunk_extension_almost_done:
1745 if (ch == LF) {
1746 state = sw_chunk_data;
1747 break;
1748 }
1749 goto invalid;
1750
1751 case sw_chunk_data:
1752 rc = NGX_OK;
1753 goto data;
1754
1755 case sw_after_data:
1756 switch (ch) {
1757 case CR:
1758 state = sw_after_data_almost_done;
1759 break;
1760 case LF:
1761 state = sw_chunk_start;
1762 }
1763 break;
1764
1765 case sw_after_data_almost_done:
1766 if (ch == LF) {
1767 state = sw_chunk_start;
1768 break;
1769 }
1770 goto invalid;
1771
1772 case sw_last_chunk_extension:
1773 switch (ch) {
1774 case CR:
1775 state = sw_last_chunk_extension_almost_done;
1776 break;
1777 case LF:
1778 state = sw_trailer;
1779 }
1780 break;
1781
1782 case sw_last_chunk_extension_almost_done:
1783 if (ch == LF) {
1784 state = sw_trailer;
1785 break;
1786 }
1787 goto invalid;
1788
1789 case sw_trailer:
1790 switch (ch) {
1791 case CR:
1792 state = sw_trailer_almost_done;
1793 break;
1794 case LF:
1795 goto done;
1796 default:
1797 state = sw_trailer_header;
1798 }
1799 break;
1800
1801 case sw_trailer_almost_done:
1802 if (ch == LF) {
1803 goto done;
1804 }
1805 goto invalid;
1806
1807 case sw_trailer_header:
1808 switch (ch) {
1809 case CR:
1810 state = sw_trailer_header_almost_done;
1811 break;
1812 case LF:
1813 state = sw_trailer;
1814 }
1815 break;
1816
1817 case sw_trailer_header_almost_done:
1818 if (ch == LF) {
1819 state = sw_trailer;
1820 break;
1821 }
1822 goto invalid;
1823
1824 }
1825 }
1826
1827 data:
1828
1829 ctx->state = state;
1830 buf->pos = pos;
1831
1832 switch (state) {
1833
1834 case sw_chunk_start:
1835 ctx->length = 3 /* "0" LF LF */;
1836 break;
1837 case sw_chunk_size:
1838 ctx->length = 2 /* LF LF */
1839 + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */ : 0);
1840 break;
1841 case sw_chunk_extension:
1842 case sw_chunk_extension_almost_done:
1843 ctx->length = 1 /* LF */ + ctx->size + 4 /* LF "0" LF LF */;
1844 break;
1845 case sw_chunk_data:
1846 ctx->length = ctx->size + 4 /* LF "0" LF LF */;
1847 break;
1848 case sw_after_data:
1849 case sw_after_data_almost_done:
1850 ctx->length = 4 /* LF "0" LF LF */;
1851 break;
1852 case sw_last_chunk_extension:
1853 case sw_last_chunk_extension_almost_done:
1854 ctx->length = 2 /* LF LF */;
1855 break;
1856 case sw_trailer:
1857 case sw_trailer_almost_done:
1858 ctx->length = 1 /* LF */;
1859 break;
1860 case sw_trailer_header:
1861 case sw_trailer_header_almost_done:
1862 ctx->length = 2 /* LF LF */;
1863 break;
1864
1865 }
1866
1867 return rc;
1868
1869 done:
1870
1871 return NGX_DONE;
1872
1873 invalid:
1874
1875 return NGX_ERROR;
1876 }
1877
1878
1879 static ngx_int_t 1617 static ngx_int_t
1880 ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) 1618 ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1881 { 1619 {
1882 ngx_int_t rc; 1620 ngx_int_t rc;
1883 ngx_buf_t *b, **prev; 1621 ngx_buf_t *b, **prev;
1899 b = NULL; 1637 b = NULL;
1900 prev = &buf->shadow; 1638 prev = &buf->shadow;
1901 1639
1902 for ( ;; ) { 1640 for ( ;; ) {
1903 1641
1904 rc = ngx_http_proxy_parse_chunked(r, buf); 1642 rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
1905 1643
1906 if (rc == NGX_OK) { 1644 if (rc == NGX_OK) {
1907 1645
1908 /* a chunk has been parsed successfully */ 1646 /* a chunk has been parsed successfully */
1909 1647
1950 /* STUB */ b->num = buf->num; 1688 /* STUB */ b->num = buf->num;
1951 1689
1952 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0, 1690 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
1953 "input buf #%d %p", b->num, b->pos); 1691 "input buf #%d %p", b->num, b->pos);
1954 1692
1955 if (buf->last - buf->pos >= ctx->size) { 1693 if (buf->last - buf->pos >= ctx->chunked.size) {
1956 1694
1957 buf->pos += ctx->size; 1695 buf->pos += ctx->chunked.size;
1958 b->last = buf->pos; 1696 b->last = buf->pos;
1959 ctx->size = 0; 1697 ctx->chunked.size = 0;
1960 1698
1961 continue; 1699 continue;
1962 } 1700 }
1963 1701
1964 ctx->size -= buf->last - buf->pos; 1702 ctx->chunked.size -= buf->last - buf->pos;
1965 buf->pos = buf->last; 1703 buf->pos = buf->last;
1966 b->last = buf->last; 1704 b->last = buf->last;
1967 1705
1968 continue; 1706 continue;
1969 } 1707 }
1980 1718
1981 if (rc == NGX_AGAIN) { 1719 if (rc == NGX_AGAIN) {
1982 1720
1983 /* set p->length, minimal amount of data we want to see */ 1721 /* set p->length, minimal amount of data we want to see */
1984 1722
1985 p->length = ctx->length; 1723 p->length = ctx->chunked.length;
1986 1724
1987 break; 1725 break;
1988 } 1726 }
1989 1727
1990 /* invalid response */ 1728 /* invalid response */
1995 return NGX_ERROR; 1733 return NGX_ERROR;
1996 } 1734 }
1997 1735
1998 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1736 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1999 "http proxy chunked state %d, length %d", 1737 "http proxy chunked state %d, length %d",
2000 ctx->state, p->length); 1738 ctx->chunked.state, p->length);
2001 1739
2002 if (b) { 1740 if (b) {
2003 b->shadow = buf; 1741 b->shadow = buf;
2004 b->last_shadow = 1; 1742 b->last_shadow = 1;
2005 1743
2092 ll = &cl->next; 1830 ll = &cl->next;
2093 } 1831 }
2094 1832
2095 for ( ;; ) { 1833 for ( ;; ) {
2096 1834
2097 rc = ngx_http_proxy_parse_chunked(r, buf); 1835 rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
2098 1836
2099 if (rc == NGX_OK) { 1837 if (rc == NGX_OK) {
2100 1838
2101 /* a chunk has been parsed successfully */ 1839 /* a chunk has been parsed successfully */
2102 1840
2114 b->memory = 1; 1852 b->memory = 1;
2115 1853
2116 b->pos = buf->pos; 1854 b->pos = buf->pos;
2117 b->tag = u->output.tag; 1855 b->tag = u->output.tag;
2118 1856
2119 if (buf->last - buf->pos >= ctx->size) { 1857 if (buf->last - buf->pos >= ctx->chunked.size) {
2120 buf->pos += ctx->size; 1858 buf->pos += ctx->chunked.size;
2121 b->last = buf->pos; 1859 b->last = buf->pos;
2122 ctx->size = 0; 1860 ctx->chunked.size = 0;
2123 1861
2124 } else { 1862 } else {
2125 ctx->size -= buf->last - buf->pos; 1863 ctx->chunked.size -= buf->last - buf->pos;
2126 buf->pos = buf->last; 1864 buf->pos = buf->last;
2127 b->last = buf->last; 1865 b->last = buf->last;
2128 } 1866 }
2129 1867
2130 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1868 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,